293 lines
6.6 KiB
Markdown
293 lines
6.6 KiB
Markdown
# FILE: MOD4.5_SIEM_Operations.md
|
|
# MODULE 4.5: SIEM OPERATIONS & LOG ANALYSIS
|
|
|
|
## Learning Objectives
|
|
- Master KQL (Kibana Query Language) for Security Onion
|
|
- Build custom dashboards for threat visualization
|
|
- Perform log correlation across multiple data sources
|
|
- Tune alerts to reduce false positives
|
|
- Export data for integration with custom SOC dashboard (React)
|
|
|
|
---
|
|
|
|
## LAB 4.5.1: KIBANA QUERY LANGUAGE (KQL) FUNDAMENTALS
|
|
|
|
### Basic KQL Syntax
|
|
```
|
|
# Search for specific field value
|
|
event.module: "suricata"
|
|
source.ip: "10.10.2.50"
|
|
|
|
# Multiple conditions (AND)
|
|
event.module: "suricata" AND alert.signature: "GPL EXPLOIT"
|
|
|
|
# OR condition
|
|
source.ip: ("10.10.2.50" OR "10.10.2.51")
|
|
|
|
# Wildcards
|
|
alert.signature: *nmap*
|
|
|
|
# NOT operator
|
|
event.module: "suricata" NOT alert.severity: 3
|
|
|
|
# Field exists
|
|
_exists_: alert.signature
|
|
|
|
# Range queries
|
|
event.duration: >=1000000
|
|
@timestamp: >= "2026-02-11T00:00:00"
|
|
|
|
# Nested field
|
|
dns.question.name: "evil.com"
|
|
```
|
|
|
|
### Common SOC Queries
|
|
|
|
**Find failed SSH logins:**
|
|
```
|
|
event.dataset: "system.auth" AND system.auth.ssh.event: "Failed"
|
|
```
|
|
|
|
**Detect port scans (high SYN packet count):**
|
|
```
|
|
event.module: "suricata" AND network.transport: "tcp" AND suricata.eve.flow.pkts_toserver: >100
|
|
```
|
|
|
|
**Find DNS queries to suspicious domains:**
|
|
```
|
|
dns.question.name: (*malware* OR *phishing* OR *bad*)
|
|
```
|
|
|
|
**High-severity alerts:**
|
|
```
|
|
alert.severity: (1 OR 2) AND event.module: "suricata"
|
|
```
|
|
|
|
---
|
|
|
|
## LAB 4.5.2: BUILDING CUSTOM DASHBOARDS
|
|
|
|
### Create Attack Detection Dashboard
|
|
|
|
```
|
|
1. Navigate to: Kibana > Dashboard > Create new dashboard
|
|
|
|
2. Add Visualization: Top Attack Signatures
|
|
- Click "Create visualization"
|
|
- Type: Vertical bar chart
|
|
- Index pattern: so-*
|
|
- Metrics: Count
|
|
- Buckets: Terms → alert.signature.keyword
|
|
- Top 10
|
|
- Save: "Top Attack Signatures"
|
|
|
|
3. Add Visualization: Alert Timeline
|
|
- Type: Line chart
|
|
- X-axis: Date Histogram → @timestamp
|
|
- Y-axis: Count
|
|
- Save: "Alert Timeline"
|
|
|
|
4. Add Visualization: Source IP Geo Map
|
|
- Type: Maps
|
|
- Add layer: Documents
|
|
- Index: so-*
|
|
- Geospatial field: source.geo.location
|
|
- Save: "Attack Source Map"
|
|
|
|
5. Add Visualization: Alert Severity Breakdown
|
|
- Type: Pie chart
|
|
- Slice: Terms → alert.severity
|
|
- Save: "Severity Distribution"
|
|
|
|
6. Save Dashboard: "Apophis SOC - Attack Overview"
|
|
```
|
|
|
|
---
|
|
|
|
## LAB 4.5.3: DASHBOARD INTEGRATION WITH REACT SOC
|
|
|
|
### Export Data for Mock Dashboard
|
|
|
|
```bash
|
|
# Query Security Onion for last 24h alerts
|
|
# In Kibana Dev Tools:
|
|
|
|
POST /so-*/_search
|
|
{
|
|
"size": 100,
|
|
"query": {
|
|
"bool": {
|
|
"must": [
|
|
{ "range": { "@timestamp": { "gte": "now-24h" } } }
|
|
]
|
|
}
|
|
},
|
|
"sort": [
|
|
{ "@timestamp": { "order": "desc" } }
|
|
]
|
|
}
|
|
|
|
# Export to JSON, then process for React dashboard:
|
|
|
|
# On Security Onion, create export script:
|
|
cat > /home/analyst/export_dashboard_data.sh << 'EOF'
|
|
#!/bin/bash
|
|
# Export SOC data for dashboard integration
|
|
|
|
# Export alert counts
|
|
curl -X GET "localhost:9200/so-*/_search?pretty" -H 'Content-Type: application/json' -d'
|
|
{
|
|
"size": 0,
|
|
"aggs": {
|
|
"severity_count": {
|
|
"terms": { "field": "alert.severity" }
|
|
}
|
|
}
|
|
}
|
|
' > /tmp/severity_data.json
|
|
|
|
# Export top threats
|
|
curl -X GET "localhost:9200/so-*/_search?pretty" -H 'Content-Type: application/json' -d'
|
|
{
|
|
"size": 0,
|
|
"aggs": {
|
|
"top_signatures": {
|
|
"terms": { "field": "alert.signature.keyword", "size": 10 }
|
|
}
|
|
}
|
|
}
|
|
' > /tmp/top_threats.json
|
|
|
|
echo "Data exported to /tmp/"
|
|
EOF
|
|
|
|
chmod +x /home/analyst/export_dashboard_data.sh
|
|
./export_dashboard_data.sh
|
|
|
|
# Transfer to dashboard development environment
|
|
scp /tmp/*.json user@dashboard-host:~/seclab/dashboard/src/data/live/
|
|
```
|
|
|
|
### Convert to React Mock Data Format
|
|
|
|
```javascript
|
|
// In dashboard/src/data/mockData.js, add real data integration:
|
|
|
|
export const importSecurityOnionData = async () => {
|
|
// In production, this would fetch from Security Onion API
|
|
// For now, use exported JSON files
|
|
|
|
const severityData = {
|
|
critical: 45,
|
|
high: 128,
|
|
medium: 312,
|
|
low: 891
|
|
};
|
|
|
|
const topThreats = [
|
|
{ ip: "203.0.113.50", count: 1247, country: "CN", severity: "critical" },
|
|
{ ip: "198.51.100.23", count: 892, country: "RU", severity: "high" },
|
|
// ... from exported data
|
|
];
|
|
|
|
return { severityData, topThreats };
|
|
};
|
|
```
|
|
|
|
---
|
|
|
|
## LAB 4.5.4: ALERT TUNING & FALSE POSITIVE REDUCTION
|
|
|
|
### Identify Noisy Rules
|
|
|
|
```
|
|
# In Kibana, find most frequent alerts:
|
|
POST /so-*/_search
|
|
{
|
|
"size": 0,
|
|
"aggs": {
|
|
"signatures": {
|
|
"terms": {
|
|
"field": "alert.signature.keyword",
|
|
"size": 20,
|
|
"order": { "_count": "desc" }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# Common false positives:
|
|
# - Internal vulnerability scanners (Nessus, OpenVAS)
|
|
# - Legitimate admin tools (Nmap from IT)
|
|
# - Noisy signatures (DNS ANY query, etc.)
|
|
```
|
|
|
|
### Suppress False Positives
|
|
|
|
```bash
|
|
# Edit Suricata threshold.config
|
|
sudo nano /etc/suricata/threshold.config
|
|
|
|
# Suppress specific signature for specific IP
|
|
suppress gen_id 1, sig_id 2100498, track by_src, ip 10.10.3.50
|
|
# Signature 2100498 from source 10.10.3.50 will be suppressed
|
|
|
|
# Rate limit alerts (max 5 per 60 seconds)
|
|
threshold gen_id 1, sig_id 2010937, type threshold, track by_src, count 5, seconds 60
|
|
|
|
# Restart Suricata
|
|
sudo so-suricata-restart
|
|
```
|
|
|
|
---
|
|
|
|
## LAB 4.5.5: LOG CORRELATION
|
|
|
|
### Multi-Source Event Correlation
|
|
|
|
**Scenario:** Detect full attack chain (scan → exploit → command execution)
|
|
|
|
```
|
|
# Step 1: Find nmap scan in Suricata
|
|
alert.signature: "GPL SCAN nmap*" AND source.ip: "10.10.2.50"
|
|
# Note timestamp: 2026-02-11T14:30:00
|
|
|
|
# Step 2: Find exploit attempt within 10 minutes
|
|
@timestamp: ["2026-02-11T14:30:00" TO "2026-02-11T14:40:00"]
|
|
AND alert.signature: *exploit*
|
|
AND destination.ip: "10.10.4.10"
|
|
|
|
# Step 3: Find Zeek connection logs showing data transfer
|
|
event.dataset: "zeek.conn"
|
|
AND source.ip: "10.10.2.50"
|
|
AND destination.ip: "10.10.4.10"
|
|
AND zeek.conn.orig_bytes: >10000
|
|
AND @timestamp: ["2026-02-11T14:35:00" TO "2026-02-11T14:45:00"]
|
|
|
|
# Step 4: Build correlation rule (in Kibana detection rules)
|
|
{
|
|
"name": "Attack Chain: Scan to Exploit",
|
|
"description": "Detects nmap scan followed by exploit attempt",
|
|
"index": ["so-*"],
|
|
"query": "sequence by source.ip with maxspan=15m
|
|
[alert.signature: \"GPL SCAN nmap*\"]
|
|
[alert.signature: *exploit*]"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
##DELIVERABLES
|
|
|
|
- [ ] Custom Kibana dashboard with 5+ visualizations
|
|
- [ ] KQL query library (saved searches for common threats)
|
|
- [ ] Alert tuning configuration (threshold.config)
|
|
- [ ] Correlation rule for attack chain detection
|
|
- [ ] Data export script for React dashboard integration
|
|
|
|
---
|
|
|
|
**END OF MODULE 4.5**
|
|
|
|
Proceed to **MOD5: Active Directory Threat Emulation** after mastering SIEM query skills.
|