Einleitung
Brute-Force- und Password-Spraying-Angriffe laufen selten „sauber“ auf einem einzigen System. In realen SIEM-Szenarien verteilen sich fehlgeschlagene Anmeldungen über verschiedene Hosts, Dienste und Logquellen – oft mit identischem Quell-IP-Adressraum oder identischem Benutzernamen. Wazuh kann solche Muster grundsätzlich über Frequenz-/Zeitfenster-Regeln korrelieren. In der Praxis scheitern entsprechende Custom Rules jedoch häufig daran, dass die Korrelation nicht auf Gruppenbasis auslöst. Dieser Beitrag erklärt die Ursache, ordnet sie in die Wazuh-Architektur ein und zeigt praxistaugliche Workarounds.
Ausgangslage / Problemstellung
Es existieren bereits Alerts zu „authentication failed“. Diese Events enthalten Felder wie srcip und dstuser (bzw. im Alert-JSON häufig unter data.*). Darauf aufbauend sollen Korrelationen greifen, z. B.:
- Mehrere fehlgeschlagene Authentifizierungen von derselben IP innerhalb von 120 Sekunden
- Mehrere fehlgeschlagene Authentifizierungen für denselben User innerhalb von 120 Sekunden
Versuche mit frequency/timeframe und <if_matched_group>authentication_failed</if_matched_group> triggern nicht – obwohl die Basis-Events sichtbar sind und identische Felder wiederholt auftreten. Ersetzt man <if_matched_group> durch <if_matched_sid>, funktioniert es.
Technische Analyse
1) Wie Wazuh-Korrelation technisch arbeitet
Die klassische Rule-Engine (wazuh-analysisd) verarbeitet Events in einer Pipeline:
- Decoding: Felder wie
srcip,dstuser,user,idwerden extrahiert. - Rules: Ein Event kann eine oder mehrere Rules matchen (in der aktuellen Engine jedoch mit Einschränkungen).
- Korrelation: Einige Regeln können über
frequency/timeframeund „same_*“-Bedingungen wiederkehrende Ereignisse korrelieren.
Wichtig: Die Korrelation ist im aktuellen wazuh-analysisd funktional, aber in der Tiefe limitiert – insbesondere bei komplexen Abhängigkeiten („Regeln auf Gruppen, die wiederum durch andere Regeln gesetzt werden“).
2) Warum <if_matched_group> in diesem Szenario nicht zuverlässig ist
<if_matched_group> klingt wie der naheliegende Ansatz („korreliere alles, was zur Gruppe authentication_failed gehört“). In der Praxis stößt man hier aber auf eine Einschränkung: Die Korrelation über Gruppenzuordnung kann als eine Art „verschachtelte Korrelation“ wirken – das heißt, die Korrelationsregel erwartet einen stabil referenzierbaren Match-Kontext, den analysisd nicht in allen Fällen über Gruppen sauber aufbaut.
Das Ergebnis: Basis-Regeln feuern (und vergeben Gruppen), aber die Korrelationsregel bekommt diese Gruppenzuordnung nicht so „greifbar“, dass sie zuverlässig über frequency/timeframe darauf korrelieren kann.
3) Feldnamen: dstuser vs. data.dstusr vs. data.dstuser
Ein zusätzlicher Stolperstein ist die Benennung von Feldern:
- In Rules werden typischerweise Decoder-Felder verwendet (
srcip,dstuser,user, …). - In Alerts/JSON sieht man oft dieselben Werte als
data.*-Struktur.
Für <same_field> musst du genau das Feld angeben, das die Rule-Engine intern als Feld kennt. Wenn du im Alert-Output „data.dstusr“ siehst, heißt das nicht automatisch, dass im Rule-Context dstusr existiert. In vielen Integrationen ist es dstuser oder user. Ein falscher Feldname verhindert Korrelation vollständig.
Lösung / Best Practices
Workaround 1: Von <if_matched_group> auf <if_matched_sid> wechseln (stabilster Ansatz)
Statt auf die Gruppe zu zielen, korrelierst du explizit auf die Rule IDs der Basis-Regeln, die die einzelnen „authentication failed“-Events erzeugen.
Beispiel (Schema):
<rule id="555102" level="10" frequency="4" timeframe="120">
<if_matched_sid>BASE_RULE_ID_1,BASE_RULE_ID_2,BASE_RULE_ID_3</if_matched_sid>
<description>Viele fehlgeschlagene Authentifizierungen von derselben IP</description>
<same_srcip/>
</rule>
<rule id="555103" level="10" frequency="4" timeframe="120">
<if_matched_sid>BASE_RULE_ID_1,BASE_RULE_ID_2,BASE_RULE_ID_3</if_matched_sid>
<description>Viele fehlgeschlagene Authentifizierungen für denselben Benutzer</description>
<same_field>dstuser</same_field>
</rule>
Wichtig in der Praxis:
- Trage alle relevanten Basis-Rule-IDs ein (z. B. Windows, Linux, VPN, Web-App Auth, IAM).
- Erhöhe
frequencyrealistisch (2–3 kann im Rauschen untergehen; 4–10 ist oft sinnvoller). - Nutze bei User-Korrelation bevorzugt
<same_field>dstuser</same_field>oder<same_user/>nur dann, wenn du sicher bist, welches Feld bei deinen Quellen wirklich befüllt wird.
Workaround 2: Einheitliche „Basisregel“ schaffen und darauf korrelieren
Wenn deine „authentication failed“-Events aus verschiedenen Quellen stammen und sehr unterschiedliche Basis-Regeln feuern, lohnt sich eine Normalisierung:
- Erstelle eine eigene Rule, die alle relevanten Auth-Fail-Events zuverlässig matcht (z. B. per
<if_group>/<if_sid>/<match>je nach Quelle) und einheitlich taggt. - Korrigiere/normalisiere Felder über Decoder/Integration (z. B. sicherstellen, dass
dstuserüberall befüllt ist). - Korrelieren dann ausschließlich auf diese Rule-ID via
<if_matched_sid>.
Das reduziert Pflegeaufwand erheblich.
Workaround 3: Feldvalidierung vor Korrelation erzwingen
Wenn du same_field nutzt, stelle sicher, dass das Feld für alle korrelierten Events existiert. Eine robuste Technik ist eine zusätzliche Bedingung:
<rule id="555105" level="10" frequency="4" timeframe="120">
<if_matched_sid>BASE_RULE_IDs</if_matched_sid>
<field name="dstuser">\S+</field>
<description>Viele fehlgeschlagene Authentifizierungen für denselben Benutzer</description>
<same_field>dstuser</same_field>
</rule>
Damit korrelierst du nicht auf Events, in denen der User leer/uneinheitlich ist.
Lessons Learned / Best Practices
- Korrelation auf Gruppenbasis ist in der aktuellen
wazuh-analysisd-Engine nicht in allen Fällen zuverlässig; für produktive Korrelationen ist<if_matched_sid>die sicherere Wahl. - Feldnamen zuerst verifizieren: Nutze
wazuh-logtestbzw. den tatsächlichen Rule-Context, nicht nur den Alert-JSON-Output. Entscheidend ist, obsrcip,dstuser,userim Decoder-Kontext existieren. - Baue Korrelationen gegen eine normalisierte Basisregel, wenn du mehrere Systeme/Quellen zusammenführen willst.
- Setze Schwellenwerte (frequency/timeframe) so, dass sie echte Angriffe abbilden und nicht durch reguläre Fehlbedienung feuern.
- Plane mittelfristig damit, dass die Engine-Weiterentwicklung (Wazuh Engine als Nachfolger von
analysisd) diese Klasse von Einschränkungen deutlich entschärfen soll; bis dahin sind explizite Rule-ID-Korrelationen das stabilste Muster.
Referenzen (Engine-/Korrelationseinschränkungen):
- GitHub Issue: 27488
- GitHub Issue: 3291
- GitHub Issue: 29585
Fazit
Wenn „Many failed authentication“-Korrelationen in Wazuh nicht triggern, obwohl Basis-Alerts vorhanden sind, liegt die Ursache häufig nicht in frequency/timeframe, sondern in der Art, wie wazuh-analysisd Korrelationen über Gruppen behandelt. Der praxistaugliche Workaround ist, konsequent auf <if_matched_sid> zu wechseln und auf die Rule-IDs der Basis-Detections zu korrelieren – ergänzt um saubere Feldnormalisierung (z. B. dstuser) und Feldvalidierung. Damit bekommst du robuste Brute-Force-/Password-Spraying-Detections über heterogene Systeme hinweg.
Mehr zu Wazuh …
https://wazuh.com/?utm_source=ambassadors&utm_medium=referral&utm_campaign=ambassadors+program
Mehr zum Wazuh Ambassador Program …
https://wazuh.com/ambassadors-program/?utm_source=ambassadors&utm_medium=referral&utm_campaign=ambassadors+program
https://wazuh.slack.com/archives/C0A933R8E/p1768557314871879