Wazuh Portscan erkennen
Dieser Artikel beschreibt, wie ein Portscan im SOC-Lab erkannt wird: Der Suricata-East-West-Sensor (OVS-Mirror, port23) erzeugt pro SYN ein Event, und der Wazuh-Manager korreliert diese Events zu einem Scan-Alarm. Dadurch werden auch laterale Scans innerhalb eines VLANs erkannt, die die OPNsense nie zu sehen bekommt.
Wirkprinzip
- Zwei Stufen – der Sensor sieht, der Manager urteilt
- Suricata kennt keinen Zustand über die Zeit und betrachtet jedes Paket einzeln. Es liefert pro SYN nur ein Roh-Event.
- Das Zählen über ein Zeitfenster (gleiche Quelle, viele Ziele) übernimmt ausschließlich der Wazuh-Manager per
frequency/timeframe.
Eine einzelne SYN-Verbindung ist normal und für sich genommen kein Alarm – erst die Häufung macht den Scan.
Stufe 1: Suricata-Regel
- Pro SYN in Richtung HOME_NET ein Event erzeugen – Datei
/etc/suricata/rules/local.rules
alert tcp any any -> $HOME_NET any (msg:"LOCAL SYN nach HOME_NET"; \
flags:S,12; flow:to_server; classtype:attempted-recon; \
sid:9000200; rev:1;)
- Regeln neu laden (ohne Neustart)
suricatasc -c reload-rules
Bewusst ohne threshold: Die Entscheidung trifft Wazuh. Ein threshold hier würde Events unterdrücken und die Korrelation aushebeln. flags:S,12 matcht das SYN-Bit und ignoriert die beiden reservierten Bits (CWR/ECE), damit auch ECN-SYNs erfasst werden.
Eve-Log an Wazuh anbinden
- Auf dem Sensor den Wazuh-Agent die
eve.jsonmitlesen lassen – Datei/var/ossec/etc/ossec.conf
<localfile>
<log_format>json</log_format>
<location>/var/log/suricata/eve.json</location>
</localfile>
Die Suricata-Alerts landen im Manager unter der Basis-Regel 86601.
Stufe 2: Wazuh-Korrelationsregeln
- Datei
/var/ossec/etc/rules/local_rules.xml
<group name="local,ids,portscan,">
<!-- Vertikal: viele verschiedene Zielports von gleicher Quelle -->
<rule id="100210" level="10" frequency="20" timeframe="10">
<if_matched_sid>86601</if_matched_sid>
<field name="alert.signature">LOCAL SYN nach HOME_NET</field>
<same_field>src_ip</same_field>
<different_field>dest_port</different_field>
<description>Moeglicher vertikaler Portscan von $(src_ip)</description>
<mitre>
<id>T1046</id>
</mitre>
<group>recon,portscan,</group>
</rule>
<!-- Horizontal: ein Port ueber viele Hosts -->
<rule id="100211" level="10" frequency="20" timeframe="10">
<if_matched_sid>86601</if_matched_sid>
<field name="alert.signature">LOCAL SYN nach HOME_NET</field>
<same_field>src_ip</same_field>
<same_field>dest_port</same_field>
<different_field>dest_ip</different_field>
<description>Moeglicher horizontaler Netz-Sweep von $(src_ip) auf Port $(dest_port)</description>
<mitre>
<id>T1046</id>
</mitre>
<group>recon,portscan,</group>
</rule>
</group>
- Manager neu starten
systemctl restart wazuh-manager
- 100210 fängt den klassischen vertikalen Portscan (ein Host, viele Ports).
- 100211 fängt den horizontalen Sweep (ein Port, viele Hosts) – typisch für Lateral-Movement-Discovery nach dem Foothold.
Stolpersteine
frequencyzählt mit Off-by-One
- Bei
frequency="20"feuern die ersten 19 Events nur die Basisregel; erst das 20. löst die Korrelation aus. Schwelle entsprechend lesen und tunen.
same_field/different_fieldnur für dynamische Felder
- Für die statischen Felder (
srcip,dstip) existieren diese Tags nicht. Hier funktioniert es, weilsrc_ip,dest_ipunddest_portdynamische JSON-Felder aus dem Suricata-Decoder sind.
different_fieldkann bei kleinen Mengen zu früh greifen
- Bekanntes Verhalten (Wazuh #16249): Wechseln sich wenige Ports ab, kann die Regel trotzdem zünden. Bei einem echten
-p--Scan irrelevant, weil hunderte verschiedene Ports kommen.
PoC mit nmap
- Vorbereitung
- Treffer live mitlesen (auf dem Manager)
tail -f /var/ossec/logs/alerts/alerts.json | grep -E '100210|100211'
- Vertikaler Portscan – viele Ports auf einem Host (von Kali)
nmap -sS -p- -T4 172.26.52.11- Erwartung: Regel 100210 (vertikaler Portscan) feuert, Level 10.
- Horizontaler Sweep – ein Port über das ganze Segment
nmap -sS -p 22 -T4 172.26.52.0/24
- Erwartung: Regel 100211 (horizontaler Sweep) feuert, Level 10.
- Im Dashboard prüfen
- Security Events → Filter
rule.id:100210bzw.rule.id:100211.
Regel testen ohne Scan
- Eine echte eve-Zeile durch die Regel-Engine schicken
/var/ossec/bin/wazuh-logtest
Eine alert-Zeile aus /var/log/suricata/eve.json einfügen und prüfen, ob 86601 dekodiert und – bei Wiederholung im Zeitfenster – 100210 greift.