Squert Cheat Sheet
Überblick
Squert ist eine webbasierte Anwendung, die eine visuelle Schnittstelle zur Abfrage und Analyse von Ereignissen bietet, die in einer Sguil-Datenbank gespeichert sind. Squert als komplementäres Tool zur traditionellen Client-Schnittstelle von Sguil entwickelt, bietet Sicherheitsanalysten eine intuitive webbasierte Plattform zur Untersuchung von Netzwerksicherheitsvorfällen und zur Durchführung von Eventkorrelationsanalysen. Die Anwendung nutzt moderne Web-Technologien, um Sicherheitsereignisdaten in interaktiven Charts, Grafiken und Tabellen zu präsentieren, wodurch es den Analysten einfacher wird, Muster, Trends und Anomalien im Netzwerkverkehr zu identifizieren.
Die Kernkraft von Squert liegt in der Fähigkeit, Rohsicherheitsereignisdaten in sinnvolle Visualisierungen zu transformieren, die eine schnelle Bedrohungsanalyse und eine Folgereaktion ermöglichen. Im Gegensatz zu herkömmlichen Kommandozeilen- oder Desktop-basierten Sicherheitstools bietet Squert eine reaktionsschnelle Web-Schnittstelle, die von jedem modernen Browser aus zugegriffen werden kann und verteilte Sicherheitsteams ermöglicht, effektiv bei Vorfalluntersuchungen und Bedrohungen zu arbeiten. Die Anwendung integriert sich nahtlos in bestehende Sguil-Bereitstellungen, wobei das gleiche MySQL-Datenbank-Backend verwendet wird und gleichzeitig verbesserte Visualisierungs- und Analysefunktionen bietet.
Die Architektur von Squert basiert auf PHP- und JavaScript-Technologien, wobei der Fokus darauf liegt, Echtzeit-Zugriff auf Sicherheitsereignisdaten über dynamische Web-Schnittstellen bereitzustellen. Die Anwendung unterstützt erweiterte Filter-, Such- und Korrelationsfunktionen, die es Analysten ermöglichen, in bestimmte Ereignisse einzudringen, entsprechende Aktivitäten zu untersuchen und umfassende Berichte für Management- und Compliance-Ziele zu erstellen. Mit seinem Schwerpunkt auf Usability und visuelle Analyse ist Squert ein wesentlicher Bestandteil vieler Sicherheits-Operationszentren geworden, die versuchen, ihre Ansprech-Workflows zu modernisieren.
Installation
Ubuntu/Debian Installation
Installation von Squert auf Ubuntu/Debian-Systemen:
```bash
Update system packages
sudo apt update && sudo apt upgrade -y
Install required dependencies
sudo apt install -y apache2 php php-mysql php-gd php-curl php-json \ php-xml php-mbstring libapache2-mod-php mysql-client git wget curl
Enable Apache modules
sudo a2enmod rewrite sudo a2enmod ssl
Download Squert
cd /var/www sudo git clone https://github.com/int13h/squert.git sudo chown -R www-data:www-data squert
Create Squert configuration directory
sudo mkdir -p /etc/squert sudo chown www-data:www-data /etc/squert
Set proper permissions
sudo chmod 755 /var/www/squert sudo chmod -R 644 /var/www/squert/* sudo chmod 755 /var/www/squert/scripts
Create Apache virtual host
sudo cat > /etc/apache2/sites-available/squert.conf << 'EOF'
<Directory /var/www/squert>
Options -Indexes
AllowOverride All
Require all granted
</Directory>
# Security headers
Header always set X-Content-Type-Options nosniff
Header always set X-Frame-Options DENY
Header always set X-XSS-Protection "1; mode=block"
ErrorLog $\\\\{APACHE_LOG_DIR\\\\}/squert_error.log
CustomLog $\\\\{APACHE_LOG_DIR\\\\}/squert_access.log combined
EOF
Enable site and restart Apache
sudo a2ensite squert.conf sudo systemctl restart apache2
Create database user for Squert
mysql -u root -p ``<< 'EOF' CREATE USER 'squert'@'localhost' IDENTIFIED BY 'squertpassword'; GRANT SELECT ON sguildb.* TO 'squert'@'localhost'; FLUSH PRIVILEGES; EOF ```_
CentOS/RHEL Installation
```bash
Install EPEL repository
sudo yum install -y epel-release
Install required packages
sudo yum install -y httpd php php-mysql php-gd php-curl php-json \ php-xml php-mbstring mysql git wget curl
Start and enable Apache
sudo systemctl start httpd sudo systemctl enable httpd
Download Squert
cd /var/www/html sudo git clone https://github.com/int13h/squert.git sudo chown -R apache:apache squert
Create configuration directory
sudo mkdir -p /etc/squert sudo chown apache:apache /etc/squert
Configure SELinux (if enabled)
sudo setsebool -P httpd_can_network_connect 1 sudo setsebool -P httpd_can_network_connect_db 1
Create Apache configuration
sudo cat >`` /etc/httpd/conf.d/squert.conf << 'EOF' Alias /squert /var/www/html/squert
Restart Apache
sudo systemctl restart httpd
Configure firewall
sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --permanent --add-service=https sudo firewall-cmd --reload ```_
Docker Installation
Laufen von Squert in Docker Containern:
```bash
Create Docker network
docker network create squert-network
Create Squert container
cat > Dockerfile.squert << 'EOF' FROM php:7.4-apache
Install required PHP extensions
RUN docker-php-ext-install mysqli pdo pdo_mysql gd
Install additional packages
RUN apt-get update && apt-get install -y \ git \ && rm -rf /var/lib/apt/lists/*
Clone Squert
RUN git clone https://github.com/int13h/squert.git /var/www/html/squert
Set permissions
RUN chown -R www-data:www-data /var/www/html/squert RUN chmod -R 755 /var/www/html/squert
Create configuration directory
RUN mkdir -p /etc/squert && chown www-data:www-data /etc/squert
Apache configuration
COPY squert.conf /etc/apache2/sites-available/ RUN a2ensite squert && a2enmod rewrite
EXPOSE 80
CMD ["apache2-foreground"] EOF
Create Apache configuration for container
cat > squert.conf << 'EOF'
<Directory /var/www/html/squert>
Options -Indexes
AllowOverride All
Require all granted
</Directory>
ErrorLog $\\\\{APACHE_LOG_DIR\\\\}/squert_error.log
CustomLog $\\\\{APACHE_LOG_DIR\\\\}/squert_access.log combined
EOF
Build and run Squert container
docker build -f Dockerfile.squert -t squert . docker run -d --name squert \ --network squert-network \ -p 8080:80 \ -v squert-config:/etc/squert \ squert
Connect to existing Sguil MySQL container
docker run -d --name squert-app \ --network squert-network \ -p 8080:80 \ -e MYSQL_HOST=sguil-mysql \ -e MYSQL_USER=squert \ -e MYSQL_PASSWORD=squertpassword \ -e MYSQL_DATABASE=sguildb \ squert ```_
Manuelle Installation
```bash
Download latest Squert release
cd /tmp wget https://github.com/int13h/squert/archive/master.tar.gz tar -xzf master.tar.gz
Copy to web directory
sudo cp -r squert-master /var/www/squert sudo chown -R www-data:www-data /var/www/squert
Set proper permissions
sudo find /var/www/squert -type f -exec chmod 644 \\{\\} \; sudo find /var/www/squert -type d -exec chmod 755 \\{\\} \; sudo chmod +x /var/www/squert/scripts/*
Create symbolic link
sudo ln -s /var/www/squert /var/www/html/squert
Create configuration directory
sudo mkdir -p /etc/squert sudo chown www-data:www-data /etc/squert ```_
Basisnutzung
Erstkonfiguration
Squert Konfiguration einrichten:
```bash
Create Squert configuration file
sudo cat > /var/www/squert/.scripts/squert.inc << 'EOF'
EOF
Set proper permissions
sudo chown www-data:www-data /var/www/squert/.scripts/squert.inc sudo chmod 600 /var/www/squert/.scripts/squert.inc
Create database tables for Squert
mysql -u squert -p sguildb << 'EOF' -- Create Squert-specific tables CREATE TABLE IF NOT EXISTS mappings ( id INT AUTO_INCREMENT PRIMARY KEY, ip_src VARCHAR(15), ip_dst VARCHAR(15), hostname VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
CREATE TABLE IF NOT EXISTS filters ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100), filter_text TEXT, user VARCHAR(50), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
CREATE TABLE IF NOT EXISTS bookmarks ( id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(200), url TEXT, user VARCHAR(50), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); EOF ```_
Web Interface Zugriff
Zugriff und Nutzung der Squert Web-Schnittstelle:
```bash
Start Apache if not running
sudo systemctl start apache2
Check Apache status
sudo systemctl status apache2
Access Squert web interface
Open browser and navigate to:
http://your-server-ip/squert
or
http://localhost/squert
Check Apache logs for any errors
sudo tail -f /var/log/apache2/squert_error.log sudo tail -f /var/log/apache2/squert_access.log
Test database connectivity
php -r " \$conn = new mysqli('localhost', 'squert', 'squertpassword', 'sguildb'); if (\$conn->connect_error) \\{ die('Connection failed: ' . \$conn->connect_error); \\} echo 'Database connection successful\n'; \$conn->close(); " ```_
Hauptnavigation
Squert Schnittstellenkomponenten verstehen:
```bash
Main dashboard components:
1. Summary view - Overview of recent events
2. Events view - Detailed event listing
3. Charts view - Visual analytics
4. Search interface - Advanced filtering
5. Reports section - Generated reports
Key interface elements:
- Time range selector
- Event filters
- Source/destination IP analysis
- Signature analysis
- Protocol breakdown
- Geographic mapping (if enabled)
Common workflows:
1. Monitor real-time events
2. Investigate specific incidents
3. Analyze traffic patterns
4. Generate compliance reports
5. Correlate related events
```_
Erweiterte Funktionen
Individuelles Armaturenbrett
Erstellen von benutzerdefinierten Dashboards und Ansichten:
```php
db = new mysqli($dbhost, $dbuser, $dbpass, $dbname); if ($this->db->connect_error) \\\\{ die("Connection failed: " . $this->db->connect_error); \\\\} \\\\} public function getTopAttackers($limit = 10, $hours = 24) \\\\{ $query = " SELECT src_ip, COUNT(*) as event_count, COUNT(DISTINCT dst_ip) as target_count, COUNT(DISTINCT signature_id) as signature_count, MIN(timestamp) as first_seen, MAX(timestamp) as last_seen FROM event WHERE timestamp >= DATE_SUB(NOW(), INTERVAL ? HOUR) GROUP BY src_ip ORDER BY event_count DESC LIMIT ? "; $stmt = $this->db->prepare($query); $stmt->bind_param("ii", $hours, $limit); $stmt->execute(); return $stmt->get_result()->fetch_all(MYSQLI_ASSOC); \\\\} public function getTopTargets($limit = 10, $hours = 24) \\\\{ $query = " SELECT dst_ip, COUNT(*) as event_count, COUNT(DISTINCT src_ip) as attacker_count, COUNT(DISTINCT signature_id) as signature_count, MIN(timestamp) as first_seen, MAX(timestamp) as last_seen FROM event WHERE timestamp >= DATE_SUB(NOW(), INTERVAL ? HOUR) GROUP BY dst_ip ORDER BY event_count DESC LIMIT ? "; $stmt = $this->db->prepare($query); $stmt->bind_param("ii", $hours, $limit); $stmt->execute(); return $stmt->get_result()->fetch_all(MYSQLI_ASSOC); \\\\} public function getSignatureStats($hours = 24) \\\\{ $query = " SELECT signature, signature_id, COUNT(*) as event_count, COUNT(DISTINCT src_ip) as unique_sources, COUNT(DISTINCT dst_ip) as unique_targets FROM event WHERE timestamp >= DATE_SUB(NOW(), INTERVAL ? HOUR) GROUP BY signature, signature_id ORDER BY event_count DESC LIMIT 20 "; $stmt = $this->db->prepare($query); $stmt->bind_param("i", $hours); $stmt->execute(); return $stmt->get_result()->fetch_all(MYSQLI_ASSOC); \\\\} public function getHourlyEventCounts($hours = 24) \\\\{ $query = " SELECT DATE_FORMAT(timestamp, '%Y-%m-%d %H:00:00') as hour, COUNT(*) as event_count FROM event WHERE timestamp >= DATE_SUB(NOW(), INTERVAL ? HOUR) GROUP BY DATE_FORMAT(timestamp, '%Y-%m-%d %H:00:00') ORDER BY hour "; $stmt = $this->db->prepare($query); $stmt->bind_param("i", $hours); $stmt->execute(); return $stmt->get_result()->fetch_all(MYSQLI_ASSOC); \\\\} public function generateDashboardHTML() \\\\{ $topAttackers = $this->getTopAttackers(); $topTargets = $this->getTopTargets(); $signatureStats = $this->getSignatureStats(); $hourlyStats = $this->getHourlyEventCounts(); ob_start(); ?> <!DOCTYPE html>
<html>
<head>
<title>Custom Security Dashboard</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
body \\\\{ font-family: Arial, sans-serif; margin: 20px; \\\\}
.dashboard-grid \\\\{ display: grid; grid-template-columns: 1fr 1fr; gap: 20px; \\\\}
.widget \\\\{ border: 1px solid #ddd; padding: 15px; border-radius: 5px; \\\\}
.widget h3 \\\\{ margin-top: 0; color: #333; \\\\}
table \\\\{ width: 100%; border-collapse: collapse; \\\\}
th, td \\\\{ padding: 8px; text-align: left; border-bottom: 1px solid #ddd; \\\\}
th \\\\{ background-color: #f2f2f2; \\\\}
.chart-container \\\\{ width: 100%; height: 300px; \\\\}
</style>
</head>
<body>
<h1>Security Operations Dashboard</h1>
<p>Last updated: <?php echo date('Y-m-d H:i:s'); ?></p>
<div class="dashboard-grid">
<div class="widget">
<h3>Top Attackers (24h)</h3>
<table>
<tr><th>Source IP</th><th>Events</th><th>Targets</th><th>Signatures</th></tr>
<?php foreach ($topAttackers as $attacker): ?>
<tr>
<td><?php echo htmlspecialchars($attacker['src_ip']); ?></td>
<td><?php echo $attacker['event_count']; ?></td>
<td><?php echo $attacker['target_count']; ?></td>
<td><?php echo $attacker['signature_count']; ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
<div class="widget">
<h3>Top Targets (24h)</h3>
<table>
<tr><th>Target IP</th><th>Events</th><th>Attackers</th><th>Signatures</th></tr>
<?php foreach ($topTargets as $target): ?>
<tr>
<td><?php echo htmlspecialchars($target['dst_ip']); ?></td>
<td><?php echo $target['event_count']; ?></td>
<td><?php echo $target['attacker_count']; ?></td>
<td><?php echo $target['signature_count']; ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
<div class="widget">
<h3>Event Timeline (24h)</h3>
<div class="chart-container">
<canvas id="timelineChart"></canvas>
</div>
</div>
<div class="widget">
<h3>Top Signatures (24h)</h3>
<table>
<tr><th>Signature</th><th>Events</th><th>Sources</th></tr>
<?php foreach (array_slice($signatureStats, 0, 10) as $sig): ?>
<tr>
<td><?php echo htmlspecialchars(substr($sig['signature'], 0, 50)) . '...'; ?></td>
<td><?php echo $sig['event_count']; ?></td>
<td><?php echo $sig['unique_sources']; ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
</div>
<script>
// Timeline chart
const ctx = document.getElementById('timelineChart').getContext('2d');
const timelineData = <?php echo json_encode($hourlyStats); ?>;
new Chart(ctx, \\\\{
type: 'line',
data: \\\\{
labels: timelineData.map(item => item.hour),
datasets: [\\\\{
label: 'Events per Hour',
data: timelineData.map(item => item.event_count),
borderColor: 'rgb(75, 192, 192)',
tension: 0.1
\\\\}]
\\\\},
options: \\\\{
responsive: true,
maintainAspectRatio: false,
scales: \\\\{
y: \\\\{
beginAtZero: true
\\\\}
\\\\}
\\\\}
\\\\});
</script>
</body>
</html>
<?php
return ob_get_clean();
\\\\}
\\}
// Generate and display dashboard $dashboard = new CustomDashboard(); echo $dashboard->generateDashboardHTML(); ?> ```_
Erweiterte Filterung und Suche
Erstellen von erweiterten Such- und Filterfunktionen:
```javascript // Advanced search interface // File: /var/www/squert/js/advanced_search.js
class AdvancedSearch \\{ constructor() \\{ this.filters = []; this.initializeInterface(); \\}
initializeInterface() \\\\{
this.createSearchForm();
this.bindEvents();
\\\\}
createSearchForm() \\\\{
const searchContainer = document.getElementById('advanced-search');
searchContainer.innerHTML = `
<div class="search-form">
<h3>Advanced Event Search</h3>
<div class="filter-group">
<label>Time Range:</label>
<select id="time-range">
<option value="1h">Last Hour</option>
<option value="6h">Last 6 Hours</option>
<option value="24h">Last 24 Hours</option>
<option value="7d">Last 7 Days</option>
<option value="30d">Last 30 Days</option>
<option value="custom">Custom Range</option>
</select>
</div>
<div class="filter-group" id="custom-time" style="display:none;">
<label>From:</label>
<input type="datetime-local" id="start-time">
<label>To:</label>
<input type="datetime-local" id="end-time">
</div>
<div class="filter-group">
<label>Source IP:</label>
<input type="text" id="src-ip" placeholder="192.168.1.1 or 192.168.1.0/24">
</div>
<div class="filter-group">
<label>Destination IP:</label>
<input type="text" id="dst-ip" placeholder="10.0.0.1 or 10.0.0.0/16">
</div>
<div class="filter-group">
<label>Port Range:</label>
<input type="text" id="port-range" placeholder="80,443,8080-8090">
</div>
<div class="filter-group">
<label>Signature:</label>
<input type="text" id="signature" placeholder="Search signature text">
</div>
<div class="filter-group">
<label>Signature ID:</label>
<input type="text" id="signature-id" placeholder="1,2,3 or 100-200">
</div>
<div class="filter-group">
<label>Protocol:</label>
<select id="protocol">
<option value="">All Protocols</option>
<option value="1">ICMP</option>
<option value="6">TCP</option>
<option value="17">UDP</option>
</select>
</div>
<div class="filter-group">
<label>Event Limit:</label>
<select id="event-limit">
<option value="100">100 events</option>
<option value="500">500 events</option>
<option value="1000">1000 events</option>
<option value="5000">5000 events</option>
</select>
</div>
<div class="filter-actions">
<button id="search-btn" class="btn-primary">Search Events</button>
<button id="save-filter-btn" class="btn-secondary">Save Filter</button>
<button id="clear-btn" class="btn-secondary">Clear All</button>
</div>
<div id="saved-filters">
<h4>Saved Filters</h4>
<div id="filter-list"></div>
</div>
</div>
<div id="search-results">
<div id="results-summary"></div>
<div id="results-table"></div>
</div>
`;
\\\\}
bindEvents() \\\\{
// Time range change
document.getElementById('time-range').addEventListener('change', (e) => \\\\{
const customTime = document.getElementById('custom-time');
customTime.style.display = e.target.value === 'custom' ? 'block' : 'none';
\\\\});
// Search button
document.getElementById('search-btn').addEventListener('click', () => \\\\{
this.performSearch();
\\\\});
// Save filter button
document.getElementById('save-filter-btn').addEventListener('click', () => \\\\{
this.saveCurrentFilter();
\\\\});
// Clear button
document.getElementById('clear-btn').addEventListener('click', () => \\\\{
this.clearAllFilters();
\\\\});
// Load saved filters
this.loadSavedFilters();
\\\\}
buildSearchQuery() \\\\{
const filters = [];
// Time range
const timeRange = document.getElementById('time-range').value;
if (timeRange !== 'custom') \\\\{
filters.push(`timestamp >= DATE_SUB(NOW(), INTERVAL $\\{timeRange.replace(/[hd]/, timeRange.includes('h') ? ' HOUR' : ' DAY')\\})`);
\\\\} else \\\\{
const startTime = document.getElementById('start-time').value;
const endTime = document.getElementById('end-time').value;
if (startTime) filters.push(`timestamp >= '$\\{startTime\\}'`);
if (endTime) filters.push(`timestamp <= '$\\{endTime\\}'`);
\\\\}
// IP addresses
const srcIp = document.getElementById('src-ip').value.trim();
if (srcIp) \\\\{
if (srcIp.includes('/')) \\\\{
// CIDR notation
filters.push(`INET_ATON(src_ip) & INET_ATON('$\\{srcIp.split('/')[1]\\}') = INET_ATON('$\\{srcIp.split('/')[0]\\}')`);
\\\\} else \\\\{
filters.push(`src_ip = '$\\{srcIp\\}'`);
\\\\}
\\\\}
const dstIp = document.getElementById('dst-ip').value.trim();
if (dstIp) \\\\{
if (dstIp.includes('/')) \\\\{
filters.push(`INET_ATON(dst_ip) & INET_ATON('$\\{dstIp.split('/')[1]\\}') = INET_ATON('$\\{dstIp.split('/')[0]\\}')`);
\\\\} else \\\\{
filters.push(`dst_ip = '$\\{dstIp\\}'`);
\\\\}
\\\\}
// Ports
const portRange = document.getElementById('port-range').value.trim();
if (portRange) \\\\{
const portConditions = [];
portRange.split(',').forEach(port => \\\\{
if (port.includes('-')) \\\\{
const [start, end] = port.split('-');
portConditions.push(`(src_port BETWEEN $\\{start\\} AND $\\{end\\}) OR (dst_port BETWEEN $\\{start\\} AND $\\{end\\})`);
\\\\} else \\\\{
portConditions.push(`src_port = $\\{port\\} OR dst_port = $\\{port\\}`);
\\\\}
\\\\});
filters.push(`($\\{portConditions.join(' OR ')\\})`);
\\\\}
// Signature
const signature = document.getElementById('signature').value.trim();
if (signature) \\\\{
filters.push(`signature LIKE '%$\\{signature\\}%'`);
\\\\}
// Signature ID
const signatureId = document.getElementById('signature-id').value.trim();
if (signatureId) \\\\{
if (signatureId.includes('-')) \\\\{
const [start, end] = signatureId.split('-');
filters.push(`signature_id BETWEEN $\\{start\\} AND $\\{end\\}`);
\\\\} else if (signatureId.includes(',')) \\\\{
filters.push(`signature_id IN ($\\{signatureId\\})`);
\\\\} else \\\\{
filters.push(`signature_id = $\\{signatureId\\}`);
\\\\}
\\\\}
// Protocol
const protocol = document.getElementById('protocol').value;
if (protocol) \\\\{
filters.push(`ip_proto = $\\{protocol\\}`);
\\\\}
return filters.join(' AND ');
\\\\}
async performSearch() \\\\{
const whereClause = this.buildSearchQuery();
const limit = document.getElementById('event-limit').value;
const query = `
SELECT
sid, cid, timestamp, src_ip, src_port, dst_ip, dst_port,
ip_proto, signature, signature_id
FROM event
$\\{whereClause ? 'WHERE ' + whereClause : ''\\}
ORDER BY timestamp DESC
LIMIT $\\{limit\\}
`;
try \\\\{
const response = await fetch('search_events.php', \\\\{
method: 'POST',
headers: \\\\{
'Content-Type': 'application/json',
\\\\},
body: JSON.stringify(\\\\{ query: query \\\\})
\\\\});
const results = await response.json();
this.displayResults(results);
\\\\} catch (error) \\\\{
console.error('Search failed:', error);
this.displayError('Search failed: ' + error.message);
\\\\}
\\\\}
displayResults(results) \\\\{
const summaryDiv = document.getElementById('results-summary');
const tableDiv = document.getElementById('results-table');
summaryDiv.innerHTML = `
<h3>Search Results</h3>
<p>Found $\\{results.length\\} events</p>
`;
if (results.length === 0) \\\\{
tableDiv.innerHTML = '<p>No events found matching the search criteria.</p>';
return;
\\\\}
let tableHTML = `
<table class="results-table">
<thead>
<tr>
<th>Timestamp</th>
<th>Source</th>
<th>Destination</th>
<th>Protocol</th>
<th>Signature</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
`;
results.forEach(event => \\\\{
tableHTML += `
<tr>
<td>$\\{event.timestamp\\}</td>
<td>$\\{event.src_ip\\}:$\\{event.src_port\\}</td>
<td>$\\{event.dst_ip\\}:$\\{event.dst_port\\}</td>
<td>$\\{this.getProtocolName(event.ip_proto)\\}</td>
<td title="$\\{event.signature\\}">$\\{event.signature.substring(0, 50)\\}...</td>
<td>
<button onclick="viewEventDetails($\\{event.sid\\}, $\\{event.cid\\})">Details</button>
<button onclick="investigateIP('$\\{event.src_ip\\}')">Investigate</button>
</td>
</tr>
`;
\\\\});
tableHTML += '</tbody></table>';
tableDiv.innerHTML = tableHTML;
\\\\}
getProtocolName(proto) \\\\{
const protocols = \\\\{ 1: 'ICMP', 6: 'TCP', 17: 'UDP' \\\\};
| return protocols[proto] | | proto; | \\}
saveCurrentFilter() \\\\{
const filterName = prompt('Enter a name for this filter:');
if (!filterName) return;
const filterData = \\\\{
name: filterName,
timeRange: document.getElementById('time-range').value,
srcIp: document.getElementById('src-ip').value,
dstIp: document.getElementById('dst-ip').value,
portRange: document.getElementById('port-range').value,
signature: document.getElementById('signature').value,
signatureId: document.getElementById('signature-id').value,
protocol: document.getElementById('protocol').value,
limit: document.getElementById('event-limit').value
\\\\};
// Save to localStorage
| const savedFilters = JSON.parse(localStorage.getItem('squert_filters') | | '[]'); | savedFilters.push(filterData); localStorage.setItem('squert_filters', JSON.stringify(savedFilters));
this.loadSavedFilters();
\\\\}
loadSavedFilters() \\\\{
| const savedFilters = JSON.parse(localStorage.getItem('squert_filters') | | '[]'); | const filterList = document.getElementById('filter-list');
filterList.innerHTML = '';
savedFilters.forEach((filter, index) => \\\\{
const filterDiv = document.createElement('div');
filterDiv.className = 'saved-filter';
filterDiv.innerHTML = `
<span>$\\{filter.name\\}</span>
<button onclick="loadFilter($\\{index\\})">Load</button>
<button onclick="deleteFilter($\\{index\\})">Delete</button>
`;
filterList.appendChild(filterDiv);
\\\\});
\\\\}
clearAllFilters() \\\\{
document.getElementById('time-range').value = '24h';
document.getElementById('src-ip').value = '';
document.getElementById('dst-ip').value = '';
document.getElementById('port-range').value = '';
document.getElementById('signature').value = '';
document.getElementById('signature-id').value = '';
document.getElementById('protocol').value = '';
document.getElementById('event-limit').value = '1000';
document.getElementById('custom-time').style.display = 'none';
\\\\}
\\}
// Initialize advanced search when page loads document.addEventListener('DOMContentLoaded', () => \\{ new AdvancedSearch(); \\});
// Global functions for event handling
function viewEventDetails(sid, cid) \\{
window.open(event_details.php?sid=$\\{sid\\}&cid;=$\\{cid\\}
, '_blank');
\\}
function investigateIP(ip) \\{
window.open(ip_investigation.php?ip=$\\{ip\\}
, '_blank');
\\}
function loadFilter(index) \\{ | const savedFilters = JSON.parse(localStorage.getItem('squert_filters') | | '[]'); | const filter = savedFilters[index];
if (filter) \\\\{
document.getElementById('time-range').value = filter.timeRange;
document.getElementById('src-ip').value = filter.srcIp;
document.getElementById('dst-ip').value = filter.dstIp;
document.getElementById('port-range').value = filter.portRange;
document.getElementById('signature').value = filter.signature;
document.getElementById('signature-id').value = filter.signatureId;
document.getElementById('protocol').value = filter.protocol;
document.getElementById('event-limit').value = filter.limit;
\\\\}
\\}
function deleteFilter(index) \\{ if (confirm('Are you sure you want to delete this filter?')) \\{ | const savedFilters = JSON.parse(localStorage.getItem('squert_filters') | | '[]'); | savedFilters.splice(index, 1); localStorage.setItem('squert_filters', JSON.stringify(savedFilters));
// Reload the filter list
const search = new AdvancedSearch();
search.loadSavedFilters();
\\\\}
\\} ```_
Automatisierte Meldung
Erstellung automatisierter Reporting-Funktionen:
```php
db = new mysqli($dbhost, $dbuser, $dbpass, $dbname); if ($this->db->connect_error) \\\\{ die("Connection failed: " . $this->db->connect_error); \\\\} $this->config = [ 'report_dir' => '/var/www/squert/reports/generated', 'email_reports' => true, 'email_to' => 'security@company.com', 'email_from' => 'squert@company.com' ]; // Create reports directory if it doesn't exist if (!is_dir($this->config['report_dir'])) \\\\{ mkdir($this->config['report_dir'], 0755, true); \\\\} \\\\} public function generateDailyReport($date = null) \\\\{ if (!$date) \\\\{ $date = date('Y-m-d', strtotime('-1 day')); \\\\} $report_data = [ 'date' => $date, 'summary' => $this->getDailySummary($date), 'top_attackers' => $this->getTopAttackers($date), 'top_targets' => $this->getTopTargets($date), 'top_signatures' => $this->getTopSignatures($date), 'hourly_stats' => $this->getHourlyStats($date), 'protocol_breakdown' => $this->getProtocolBreakdown($date), 'geographic_analysis' => $this->getGeographicAnalysis($date) ]; $html_report = $this->generateHTMLReport($report_data, 'daily'); $pdf_report = $this->generatePDFReport($report_data, 'daily'); // Save reports $html_file = $this->config['report_dir'] . "/daily_report_\\\\{$date\\\\}.html"; $pdf_file = $this->config['report_dir'] . "/daily_report_\\\\{$date\\\\}.pdf"; file_put_contents($html_file, $html_report); file_put_contents($pdf_file, $pdf_report); // Email report if configured if ($this->config['email_reports']) \\\\{ $this->emailReport($html_file, $pdf_file, "Daily Security Report - \\\\{$date\\\\}"); \\\\} return [ 'html_file' => $html_file, 'pdf_file' => $pdf_file, 'data' => $report_data ]; \\\\} public function generateWeeklyReport($week_start = null) \\\\{ if (!$week_start) \\\\{ $week_start = date('Y-m-d', strtotime('last monday')); \\\\} $week_end = date('Y-m-d', strtotime($week_start . ' +6 days')); $report_data = [ 'week_start' => $week_start, 'week_end' => $week_end, 'summary' => $this->getWeeklySummary($week_start, $week_end), 'trends' => $this->getWeeklyTrends($week_start, $week_end), 'top_incidents' => $this->getTopIncidents($week_start, $week_end), 'security_metrics' => $this->getSecurityMetrics($week_start, $week_end) ]; $html_report = $this->generateHTMLReport($report_data, 'weekly'); $html_file = $this->config['report_dir'] . "/weekly_report_\\\\{$week_start\\\\}_to_\\\\{$week_end\\\\}.html"; file_put_contents($html_file, $html_report); return ['html_file' => $html_file, 'data' => $report_data]; \\\\} private function getDailySummary($date) \\\\{ $query = " SELECT COUNT(*) as total_events, COUNT(DISTINCT src_ip) as unique_sources, COUNT(DISTINCT dst_ip) as unique_targets, COUNT(DISTINCT signature_id) as unique_signatures, MIN(timestamp) as first_event, MAX(timestamp) as last_event FROM event WHERE DATE(timestamp) = ? "; $stmt = $this->db->prepare($query); $stmt->bind_param("s", $date); $stmt->execute(); return $stmt->get_result()->fetch_assoc(); \\\\} private function getTopAttackers($date, $limit = 10) \\\\{ $query = " SELECT src_ip, COUNT(*) as event_count, COUNT(DISTINCT dst_ip) as target_count, COUNT(DISTINCT signature_id) as signature_count, GROUP_CONCAT(DISTINCT signature ORDER BY signature LIMIT 3) as top_signatures FROM event WHERE DATE(timestamp) = ? GROUP BY src_ip ORDER BY event_count DESC LIMIT ? "; $stmt = $this->db->prepare($query); $stmt->bind_param("si", $date, $limit); $stmt->execute(); return $stmt->get_result()->fetch_all(MYSQLI_ASSOC); \\\\} private function getTopTargets($date, $limit = 10) \\\\{ $query = " SELECT dst_ip, COUNT(*) as event_count, COUNT(DISTINCT src_ip) as attacker_count, COUNT(DISTINCT signature_id) as signature_count FROM event WHERE DATE(timestamp) = ? GROUP BY dst_ip ORDER BY event_count DESC LIMIT ? "; $stmt = $this->db->prepare($query); $stmt->bind_param("si", $date, $limit); $stmt->execute(); return $stmt->get_result()->fetch_all(MYSQLI_ASSOC); \\\\} private function getTopSignatures($date, $limit = 15) \\\\{ $query = " SELECT signature, signature_id, COUNT(*) as event_count, COUNT(DISTINCT src_ip) as unique_sources, COUNT(DISTINCT dst_ip) as unique_targets FROM event WHERE DATE(timestamp) = ? GROUP BY signature, signature_id ORDER BY event_count DESC LIMIT ? "; $stmt = $this->db->prepare($query); $stmt->bind_param("si", $date, $limit); $stmt->execute(); return $stmt->get_result()->fetch_all(MYSQLI_ASSOC); \\\\} private function getHourlyStats($date) \\\\{ $query = " SELECT HOUR(timestamp) as hour, COUNT(*) as event_count FROM event WHERE DATE(timestamp) = ? GROUP BY HOUR(timestamp) ORDER BY hour "; $stmt = $this->db->prepare($query); $stmt->bind_param("s", $date); $stmt->execute(); $results = $stmt->get_result()->fetch_all(MYSQLI_ASSOC); // Fill in missing hours with 0 events $hourly_stats = array_fill(0, 24, 0); foreach ($results as $row) \\\\{ $hourly_stats[$row['hour']] = $row['event_count']; \\\\} return $hourly_stats; \\\\} private function getProtocolBreakdown($date) \\\\{ $query = " SELECT ip_proto, COUNT(*) as event_count, ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM event WHERE DATE(timestamp) = ?), 2) as percentage FROM event WHERE DATE(timestamp) = ? GROUP BY ip_proto ORDER BY event_count DESC "; $stmt = $this->db->prepare($query); $stmt->bind_param("ss", $date, $date); $stmt->execute(); return $stmt->get_result()->fetch_all(MYSQLI_ASSOC); \\\\} private function generateHTMLReport($data, $type) \\\\{ ob_start(); ?> <!DOCTYPE html>
<html>
<head>
<title><?php echo ucfirst($type); ?> Security Report</title>
<style>
body \\\\{ font-family: Arial, sans-serif; margin: 20px; \\\\}
.header \\\\{ background: #f4f4f4; padding: 20px; border-radius: 5px; \\\\}
.summary \\\\{ display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin: 20px 0; \\\\}
.metric \\\\{ background: #e9e9e9; padding: 15px; border-radius: 5px; text-align: center; \\\\}
.metric h3 \\\\{ margin: 0; color: #333; \\\\}
.metric .value \\\\{ font-size: 24px; font-weight: bold; color: #007cba; \\\\}
table \\\\{ width: 100%; border-collapse: collapse; margin: 20px 0; \\\\}
th, td \\\\{ padding: 10px; text-align: left; border-bottom: 1px solid #ddd; \\\\}
th \\\\{ background-color: #f2f2f2; \\\\}
.chart \\\\{ margin: 20px 0; \\\\}
.section \\\\{ margin: 30px 0; \\\\}
.section h2 \\\\{ color: #333; border-bottom: 2px solid #007cba; padding-bottom: 5px; \\\\}
</style>
</head>
<body>
<div class="header">
<h1><?php echo ucfirst($type); ?> Security Report</h1>
<?php if ($type == 'daily'): ?>
<p>Report Date: <?php echo $data['date']; ?></p>
<?php else: ?>
<p>Report Period: <?php echo $data['week_start']; ?> to <?php echo $data['week_end']; ?></p>
<?php endif; ?>
<p>Generated: <?php echo date('Y-m-d H:i:s'); ?></p>
</div>
<?php if ($type == 'daily'): ?>
<div class="summary">
<div class="metric">
<h3>Total Events</h3>
<div class="value"><?php echo number_format($data['summary']['total_events']); ?></div>
</div>
<div class="metric">
<h3>Unique Sources</h3>
<div class="value"><?php echo number_format($data['summary']['unique_sources']); ?></div>
</div>
<div class="metric">
<h3>Unique Targets</h3>
<div class="value"><?php echo number_format($data['summary']['unique_targets']); ?></div>
</div>
<div class="metric">
<h3>Unique Signatures</h3>
<div class="value"><?php echo number_format($data['summary']['unique_signatures']); ?></div>
</div>
</div>
<div class="section">
<h2>Top Attackers</h2>
<table>
<tr><th>Source IP</th><th>Events</th><th>Targets</th><th>Signatures</th></tr>
<?php foreach ($data['top_attackers'] as $attacker): ?>
<tr>
<td><?php echo htmlspecialchars($attacker['src_ip']); ?></td>
<td><?php echo number_format($attacker['event_count']); ?></td>
<td><?php echo number_format($attacker['target_count']); ?></td>
<td><?php echo number_format($attacker['signature_count']); ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
<div class="section">
<h2>Top Targets</h2>
<table>
<tr><th>Target IP</th><th>Events</th><th>Attackers</th><th>Signatures</th></tr>
<?php foreach ($data['top_targets'] as $target): ?>
<tr>
<td><?php echo htmlspecialchars($target['dst_ip']); ?></td>
<td><?php echo number_format($target['event_count']); ?></td>
<td><?php echo number_format($target['attacker_count']); ?></td>
<td><?php echo number_format($target['signature_count']); ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
<div class="section">
<h2>Top Signatures</h2>
<table>
<tr><th>Signature</th><th>Events</th><th>Sources</th><th>Targets</th></tr>
<?php foreach ($data['top_signatures'] as $sig): ?>
<tr>
<td><?php echo htmlspecialchars($sig['signature']); ?></td>
<td><?php echo number_format($sig['event_count']); ?></td>
<td><?php echo number_format($sig['unique_sources']); ?></td>
<td><?php echo number_format($sig['unique_targets']); ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
<?php endif; ?>
</body>
</html>
<?php
return ob_get_clean();
\\\\}
private function emailReport($html_file, $pdf_file, $subject) \\\\{
// Implementation depends on your email system
// This is a basic example using PHP mail()
$to = $this->config['email_to'];
$from = $this->config['email_from'];
$headers = "From: \\\\{$from\\\\}\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=UTF-8\r\n";
$body = file_get_contents($html_file);
mail($to, $subject, $body, $headers);
\\\\}
\\}
// Usage example if (php_sapi_name() === 'cli') \\{ // Command line usage $reports = new AutomatedReports();
$action = $argv[1] ?? 'daily';
$date = $argv[2] ?? null;
switch ($action) \\\\{
case 'daily':
$result = $reports->generateDailyReport($date);
echo "Daily report generated: \\\\{$result['html_file']\\\\}\n";
break;
case 'weekly':
$result = $reports->generateWeeklyReport($date);
echo "Weekly report generated: \\\\{$result['html_file']\\\\}\n";
break;
default:
echo "Usage: php automated_reports.php [daily|weekly] [date]\n";
\\\\}
\\} ?> ```_
Automatisierungsskripte
Umfassendes Monitoring-Script
```bash
!/bin/bash
Comprehensive Squert monitoring and maintenance
Configuration
SQUERT_DIR="/var/www/squert" LOG_DIR="/var/log/squert" BACKUP_DIR="/var/backups/squert" CONFIG_FILE="/var/www/squert/.scripts/squert.inc" APACHE_LOG="/var/log/apache2/squert_error.log"
Database configuration
DB_HOST="localhost" DB_USER="squert" DB_PASS="squertpassword" DB_NAME="sguildb"
Monitoring thresholds
MAX_LOG_SIZE="100M" MAX_DISK_USAGE="90" MAX_RESPONSE_TIME="5"
Create necessary directories
mkdir -p "$LOG_DIR" "$BACKUP_DIR"
Logging function
log_message() \\{ echo "$(date '+%Y-%m-%d %H:%M:%S') - $1"|tee -a "$LOG_DIR/monitor.log" \\}
Check Squert web interface availability
check_web_interface() \\{ log_message "Checking Squert web interface..."
local response_time
response_time=$(curl -o /dev/null -s -w '%\\\\{time_total\\\\}' http://localhost/squert/ 2>/dev/null)
if [ $? -eq 0 ]; then
log_message "Web interface is accessible (response time: $\\\\{response_time\\\\}s)"
# Check if response time is acceptable
if (( $(echo "$response_time > $MAX_RESPONSE_TIME"|bc -l) )); then
log_message "WARNING: Slow response time: $\\\\{response_time\\\\}s (threshold: $\\\\{MAX_RESPONSE_TIME\\\\}s)"
return 1
fi
return 0
else
log_message "ERROR: Web interface is not accessible"
return 1
fi
\\}
Check database connectivity
check_database() \\{ log_message "Checking database connectivity..."
mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "SELECT 1;" >/dev/null 2>&1
if [ $? -eq 0 ]; then
log_message "Database connection successful"
# Check recent events
local recent_events
recent_events=$(mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" -N -e "
SELECT COUNT(*) FROM event WHERE timestamp >= DATE_SUB(NOW(), INTERVAL 1 HOUR);
" 2>/dev/null)
log_message "Recent events (last hour): $recent_events"
return 0
else
log_message "ERROR: Database connection failed"
return 1
fi
\\}
Check Apache service
check_apache() \\{ log_message "Checking Apache service..."
if systemctl is-active --quiet apache2; then
log_message "Apache service is running"
# Check for recent errors
local error_count
| error_count=$(tail -n 100 "$APACHE_LOG" 2>/dev/null | grep -c "$(date '+%Y-%m-%d')" | | echo "0") |
if [ "$error_count" -gt 10 ]; then
log_message "WARNING: High number of Apache errors today: $error_count"
fi
return 0
else
log_message "ERROR: Apache service is not running"
return 1
fi
\\}
Check disk space
check_disk_space() \\{ log_message "Checking disk space..."
local usage
| usage=$(df -h "$SQUERT_DIR" | awk 'NR==2 \\{print $5\\}' | sed 's/%//') |
log_message "Disk usage: $\\\\{usage\\\\}%"
if [ "$usage" -gt "$MAX_DISK_USAGE" ]; then
log_message "WARNING: High disk usage: $\\\\{usage\\\\}% (threshold: $\\\\{MAX_DISK_USAGE\\\\}%)"
return 1
fi
return 0
\\}
Check log file sizes
check_log_sizes() \\{ log_message "Checking log file sizes..."
find "$LOG_DIR" -name "*.log" -size +"$MAX_LOG_SIZE"|while read -r logfile; do
log_message "WARNING: Large log file: $logfile"
# Rotate large log files
if [ -f "$logfile" ]; then
mv "$logfile" "$\\\\{logfile\\\\}.$(date +%Y%m%d-%H%M%S)"
touch "$logfile"
chown www-data:www-data "$logfile"
log_message "Rotated log file: $logfile"
fi
done
\\}
Performance optimization
optimize_performance() \\{ log_message "Running performance optimization..."
# Clear PHP opcache if available
if command -v php >/dev/null 2>&1; then
php -r "if (function_exists('opcache_reset')) \\\\{ opcache_reset(); echo 'OPcache cleared\n'; \\\\}"
fi
# Optimize database tables
mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "
OPTIMIZE TABLE event;
ANALYZE TABLE event;
" >/dev/null 2>&1
log_message "Performance optimization completed"
\\}
Backup configuration
backup_configuration() \\{ log_message "Backing up Squert configuration..."
local backup_file="$BACKUP_DIR/squert-config-$(date +%Y%m%d-%H%M%S).tar.gz"
tar -czf "$backup_file" \
"$CONFIG_FILE" \
"$SQUERT_DIR/.scripts/" \
"/etc/apache2/sites-available/squert.conf" \
2>/dev/null
if [ $? -eq 0 ]; then
log_message "Configuration backup created: $backup_file"
# Keep only last 7 days of backups
find "$BACKUP_DIR" -name "squert-config-*.tar.gz" -mtime +7 -delete
return 0
else
log_message "ERROR: Configuration backup failed"
return 1
fi
\\}
Generate health report
generate_health_report() \\{ log_message "Generating health report..."
local report_file="$LOG_DIR/health-report-$(date +%Y%m%d-%H%M%S).html"
cat > "$report_file" << EOF
Squert Health Report
Generated: $(date)
System Status
Component | Status | Details |
---|---|---|
Web Interface | OK | Accessible |
Web Interface | ERROR | Not accessible |
Database | OK | Connected |
Database | ERROR | Connection failed |
Apache | OK | Running |
Apache | ERROR | Not running |
Disk Space | OK | Usage: $disk_usage |
Recent Activity
|$(tail -n 20 "$LOG_DIR/monitor.log" 2>/dev/null | | echo "No recent activity logged")|
EOF
log_message "Health report generated: $report_file"
\\}
Send alert notification
send_alert() \\{ local subject="$1" local message="$2"
# Send email if mail is configured
if command -v mail >/dev/null 2>&1; then
echo "$message"|mail -s "Squert Alert: $subject" security@company.com
fi
# Log to syslog
logger -t squert-monitor "$subject: $message"
log_message "Alert sent: $subject"
\\}
Main monitoring function
run_monitoring() \\{ log_message "Starting Squert monitoring cycle"
local issues=0
# Run all checks
| check_web_interface | | ((issues++)) | | check_database | | ((issues++)) | | check_apache | | ((issues++)) | | check_disk_space | | ((issues++)) | check_log_sizes
# Performance optimization (weekly)
if [ "$(date +%u)" -eq 1 ] && [ "$(date +%H)" -eq 2 ]; then
optimize_performance
backup_configuration
fi
# Generate health report (daily)
if [ "$(date +%H)" -eq 6 ]; then
generate_health_report
fi
# Send alerts if issues found
if [ "$issues" -gt 0 ]; then
send_alert "System Issues Detected" "Found $issues issues during monitoring. Check logs for details."
fi
log_message "Monitoring cycle completed with $issues issues"
return $issues
\\}
Maintenance functions
cleanup_old_files() \\{ log_message "Cleaning up old files..."
# Remove old log files (older than 30 days)
find "$LOG_DIR" -name "*.log.*" -mtime +30 -delete
# Remove old health reports (older than 7 days)
find "$LOG_DIR" -name "health-report-*.html" -mtime +7 -delete
# Remove old backups (older than 30 days)
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +30 -delete
log_message "Cleanup completed"
\\}
Update Squert
update_squert() \\{ log_message "Checking for Squert updates..."
| cd "$SQUERT_DIR" | | exit 1 |
# Backup current version
backup_configuration
# Check for updates
git fetch origin
local current_commit
local latest_commit
current_commit=$(git rev-parse HEAD)
latest_commit=$(git rev-parse origin/master)
if [ "$current_commit" != "$latest_commit" ]; then
log_message "Updates available, updating Squert..."
# Pull updates
git pull origin master
# Set proper permissions
chown -R www-data:www-data "$SQUERT_DIR"
find "$SQUERT_DIR" -type f -exec chmod 644 \\\\{\\\\} \;
find "$SQUERT_DIR" -type d -exec chmod 755 \\\\{\\\\} \;
# Restart Apache
systemctl restart apache2
log_message "Squert updated successfully"
else
log_message "Squert is up to date"
fi
\\}
Command line interface
case "$\\{1:-monitor\\}" in "monitor") run_monitoring ;; "cleanup") cleanup_old_files ;; "update") update_squert ;; "backup") backup_configuration ;; "report") generate_health_report ;; "optimize") optimize_performance ;; *) | echo "Usage: $0 \\{monitor | cleanup | update | backup | report | optimize\\}" | echo "" echo "Commands:" echo " monitor - Run complete monitoring cycle (default)" echo " cleanup - Clean up old files and logs" echo " update - Check for and apply Squert updates" echo " backup - Backup Squert configuration" echo " report - Generate health report" echo " optimize - Run performance optimization" exit 1 ;; esac ```_
Integrationsbeispiele
SIEM Integration
```python
!/usr/bin/env python3
Squert SIEM integration script
import mysql.connector import json import requests import time from datetime import datetime, timedelta
class SquertSIEMIntegration: def init(self, config): self.config = config self.db_config = config['database'] self.siem_config = config['siem']
def connect_database(self):
"""Connect to Squert/Sguil database"""
return mysql.connector.connect(**self.db_config)
def get_recent_events(self, minutes=5):
"""Get events from the last N minutes"""
connection = self.connect_database()
cursor = connection.cursor(dictionary=True)
query = """
SELECT
sid, cid, timestamp, src_ip, src_port, dst_ip, dst_port,
ip_proto, signature, signature_gen, signature_id, signature_rev
FROM event
WHERE timestamp >= DATE_SUB(NOW(), INTERVAL %s MINUTE)
ORDER BY timestamp DESC
"""
cursor.execute(query, (minutes,))
events = cursor.fetchall()
cursor.close()
connection.close()
return events
def transform_for_splunk(self, events):
"""Transform events for Splunk HEC"""
splunk_events = []
for event in events:
splunk_event = \\\\{
"time": int(event['timestamp'].timestamp()),
"source": "squert",
"sourcetype": "sguil:event",
"index": self.siem_config.get('splunk_index', 'security'),
"event": \\\\{
"sid": event['sid'],
"cid": event['cid'],
"timestamp": event['timestamp'].isoformat(),
"src_ip": event['src_ip'],
"src_port": event['src_port'],
"dst_ip": event['dst_ip'],
"dst_port": event['dst_port'],
"protocol": event['ip_proto'],
"signature": event['signature'],
"signature_id": event['signature_id'],
"signature_gen": event['signature_gen'],
"signature_rev": event['signature_rev']
\\\\}
\\\\}
splunk_events.append(splunk_event)
return splunk_events
def send_to_splunk(self, events):
"""Send events to Splunk via HEC"""
if not events:
return True
splunk_events = self.transform_for_splunk(events)
headers = \\\\{
'Authorization': f"Splunk \\\\{self.siem_config['splunk_token']\\\\}",
'Content-Type': 'application/json'
\\\\}
for event in splunk_events:
try:
response = requests.post(
self.siem_config['splunk_hec_url'],
headers=headers,
json=event,
verify=False,
timeout=10
)
if response.status_code != 200:
print(f"Failed to send event to Splunk: \\\\{response.status_code\\\\}")
return False
except Exception as e:
print(f"Error sending to Splunk: \\\\{e\\\\}")
return False
print(f"Sent \\\\{len(splunk_events)\\\\} events to Splunk")
return True
def transform_for_elasticsearch(self, events):
"""Transform events for Elasticsearch"""
es_events = []
for event in events:
es_event = \\\\{
"@timestamp": event['timestamp'].isoformat(),
"source": \\\\{
"ip": event['src_ip'],
"port": event['src_port']
\\\\},
"destination": \\\\{
"ip": event['dst_ip'],
"port": event['dst_port']
\\\\},
"network": \\\\{
"protocol": self.get_protocol_name(event['ip_proto'])
\\\\},
"event": \\\\{
"id": f"\\\\{event['sid']\\\\}-\\\\{event['cid']\\\\}",
"category": "network",
"type": "alert",
"severity": self.get_severity(event['signature_id'])
\\\\},
"rule": \\\\{
"id": event['signature_id'],
"name": event['signature'],
"version": event['signature_rev']
\\\\},
"sguil": \\\\{
"sid": event['sid'],
"cid": event['cid'],
"signature_gen": event['signature_gen']
\\\\}
\\\\}
es_events.append(es_event)
return es_events
def send_to_elasticsearch(self, events):
"""Send events to Elasticsearch"""
if not events:
return True
es_events = self.transform_for_elasticsearch(events)
for event in es_events:
try:
index_name = f"squert-\\\\{datetime.now().strftime('%Y.%m.%d')\\\\}"
doc_id = event['event']['id']
response = requests.post(
f"\\\\{self.siem_config['elasticsearch_url']\\\\}/\\\\{index_name\\\\}/_doc/\\\\{doc_id\\\\}",
json=event,
timeout=10
)
if response.status_code not in [200, 201]:
print(f"Failed to send event to Elasticsearch: \\\\{response.status_code\\\\}")
return False
except Exception as e:
print(f"Error sending to Elasticsearch: \\\\{e\\\\}")
return False
print(f"Sent \\\\{len(es_events)\\\\} events to Elasticsearch")
return True
def get_protocol_name(self, proto_num):
"""Convert protocol number to name"""
protocols = \\\\{1: 'icmp', 6: 'tcp', 17: 'udp'\\\\}
return protocols.get(proto_num, str(proto_num))
def get_severity(self, signature_id):
"""Determine event severity based on signature ID"""
if signature_id in [1, 2, 3]:
return 'high'
elif signature_id in [4, 5, 6]:
return 'medium'
else:
return 'low'
def run_integration(self):
"""Run the SIEM integration"""
print(f"Starting SIEM integration at \\\\{datetime.now()\\\\}")
# Get recent events
events = self.get_recent_events(5) # Last 5 minutes
if not events:
print("No new events to process")
return
print(f"Processing \\\\{len(events)\\\\} events")
# Send to configured SIEM systems
if self.siem_config.get('splunk_enabled', False):
self.send_to_splunk(events)
if self.siem_config.get('elasticsearch_enabled', False):
self.send_to_elasticsearch(events)
print("SIEM integration completed")
Configuration
config = \\{ 'database': \\{ 'host': 'localhost', 'user': 'squert', 'password': 'squertpassword', 'database': 'sguildb' \\}, 'siem': \\{ 'splunk_enabled': True, 'splunk_hec_url': 'https://splunk.company.com:8088/services/collector/event', 'splunk_token': 'your-hec-token', 'splunk_index': 'security',
'elasticsearch_enabled': True,
'elasticsearch_url': 'http://elasticsearch.company.com:9200'
\\\\}
\\}
Run integration
if name == "main": integration = SquertSIEMIntegration(config) integration.run_integration() ```_
Fehlerbehebung
Gemeinsame Themen
Web Interface nicht geladen: ```bash
Check Apache status
sudo systemctl status apache2
Check Apache error logs
sudo tail -f /var/log/apache2/squert_error.log
Check PHP errors
sudo tail -f /var/log/apache2/error.log|grep -i php
Verify file permissions
sudo chown -R www-data:www-data /var/www/squert sudo chmod -R 755 /var/www/squert
Test PHP configuration
php -m|grep -i mysql php -r "phpinfo();"|grep -i mysql ```_
** Probleme der Datenbankverbindung:** ```bash
Test database connection
mysql -h localhost -u squert -p sguildb -e "SELECT COUNT(*) FROM event;"
Check database permissions
mysql -u root -p -e "SHOW GRANTS FOR 'squert'@'localhost';"
Verify database configuration
| cat /var/www/squert/.scripts/squert.inc | grep -E "(dbhost | dbuser | dbpass | dbname)" |
Check MySQL service
sudo systemctl status mysql sudo systemctl start mysql ```_
Leistungsfragen: ```bash
Check system resources
top -p $(pgrep apache2) free -h df -h
Optimize database
mysql -u squert -p sguildb -e "OPTIMIZE TABLE event;" mysql -u squert -p sguildb -e "ANALYZE TABLE event;"
Check slow queries
mysql -u root -p -e "SHOW PROCESSLIST;"
Enable PHP OPcache
echo "opcache.enable=1" >> /etc/php/7.4/apache2/php.ini sudo systemctl restart apache2 ```_
Leistungsoptimierung
Optimierung der Squert-Leistung:
```bash
Apache optimization
cat >> /etc/apache2/conf-available/squert-performance.conf << 'EOF'
Squert performance optimizations
Enable compression
LoadModule deflate_module modules/mod_deflate.so
Enable caching
LoadModule expires_module modules/mod_expires.so
sudo a2enconf squert-performance sudo systemctl restart apache2
PHP optimization
cat >> /etc/php/7.4/apache2/conf.d/99-squert.ini << 'EOF' ; Squert PHP optimizations memory_limit = 256M max_execution_time = 60 max_input_vars = 3000
; OPcache settings opcache.enable = 1 opcache.memory_consumption = 128 opcache.interned_strings_buffer = 8 opcache.max_accelerated_files = 4000 opcache.revalidate_freq = 2 opcache.fast_shutdown = 1 EOF
sudo systemctl restart apache2
Database optimization
mysql -u root -p << 'EOF' -- Optimize Sguil database for Squert USE sguildb;
-- Add indexes for common Squert queries CREATE INDEX idx_event_timestamp_src ON event (timestamp, src_ip); CREATE INDEX idx_event_timestamp_dst ON event (timestamp, dst_ip); CREATE INDEX idx_event_signature_timestamp ON event (signature_id, timestamp); CREATE INDEX idx_event_src_dst ON event (src_ip, dst_ip);
-- Optimize table OPTIMIZE TABLE event; ANALYZE TABLE event; EOF ```_
Sicherheitsüberlegungen
Zugriffskontrolle
Web Interface Security: - Implementieren Sie HTTPS für alle Squert Zugriff - Verwenden Sie starke Authentifizierungsmechanismen - Durchführung von Sitzungszeiten und Management - Regelmäßige Sicherheitsupdates für alle Komponenten - Überwachen Sie Zugriffsprotokolle für verdächtige Aktivität
** Datenbanksicherheit:** - Verwenden Sie dedizierte Datenbankbenutzer mit minimalen Privilegien - Implementierung der Datenbank-Verbindung Verschlüsselung - Regelmäßige Aktualisierung der Datenbanksicherheit - Datenbankzugriffsprotokolle überwachen - Implementierung der Backup-Verschlüsselung
Datenschutz
Ereignisse Datensicherheit: - Verschlüsseln Sie sensible Ereignisdaten im Ruhezustand - Umsetzung von Datenschutzbestimmungen - Sicherer Zugriff auf Paketerfassungsdaten - Regelmäßige Reinigung von temporären Dateien - Implementierung der Zugangsprotokollierung für Ereignisdaten
** Sicherheit:** - Regelmäßige Sicherheitsbewertungen der Squert-Infrastruktur - Monitor für unberechtigte Zugriffsversuche - Durchführung richtiger Backup- und Recovery-Verfahren - Regelmäßige Aktualisierungen von Squert und Abhängigkeiten - Incident Response Verfahren für Squert Kompromiss
Referenzen
- [Squert GitHub Repository](https://__LINK_5___
- (__LINK_5___)
- Apache HTTP Server Dokumentation
- PHP Security Best Practices
- MySQL Performance Tuning