Einleitung
UEBA-Logik in Wazuh lebt davon, dass Basiserkennung, Klassifizierung und Korrelation sauber ineinandergreifen: erst wird ein Event zuverlässig erkannt (Parent Rule), dann kategorisiert (z. B. Severity/Incident Type), und erst darauf baut die eigentliche UEBA-Korrelation (Frequency/Timeframe/Same-field) auf. In der Praxis scheitert genau dieses Konstrukt jedoch häufig nicht an der Korrelation selbst, sondern an zwei unscheinbaren Basics: Field-Matching und Rule-Load-Reihenfolge.
Dieser Beitrag zeigt anhand eines Trellix-DLP-JSON-Feeds, warum UEBA-Regeln in einem separaten XML-File scheinbar „ignoriert“ werden, obwohl dieselbe Rule im DLP-Regelfile sofort funktioniert – und wie man das robust löst.
Ausgangslage / Problemstellung
In einer Umgebung werden Trellix DLP Events als JSON in Wazuh ingestiert. Die Rule-Struktur ist modular aufgebaut:
rules-trellix-DLP-nopalcyber.xml: Basiserkennung + Severity-KlassifizierungUEBA-rules-nopalcyber.xml: UEBA-Regeln, die auf den Parent Rules aufsetzen
Beispielaufbau (vereinfacht):
Base Rule
118100: matcht auf JSON +integration118101: klassifiziert Minor/Warning
UEBA
106201: matcht auf118101undgeneralDetails.incidentType = Email Protection106202: korreliert Wiederholungen:frequency="3"intimeframe="43200"(12h) proadditionalInformation.Sender
Symptom:
Die UEBA-Regeln triggern nicht, obwohl Tests mit Beispiel-Logs durchgeführt wurden. Sobald 106201 in dasselbe XML-File wie die Trellix-DLP-Regeln verschoben wird, funktioniert es.
Technische Analyse
In diesem Muster treten typischerweise zwei unabhängige Ursachen auf – und beide können gleichzeitig wirken:
1) Field-Mismatch: integration passt nicht zu den Logs
Die Base Rule setzt auf:
<field name="integration">ABCDcompany_Trellix_DLP</field>
Die gelieferten Logs enthalten jedoch:
"integration":"Laurus_Trellix_DLP"
Wenn die Integration nicht matcht, feuert 118100 nicht – und damit kann 118101 ebenfalls nicht feuern. Folglich hat 106201 nie eine Chance, weil sein Parent-SID nicht existiert.
Wichtig: Gerade bei Integrationsfeeds ist integration häufig der stabilste Anker – aber nur, wenn er exakt dem Payload entspricht. Ein einziges abweichendes Präfix reicht, um die komplette Kette zu „kappen“.
2) Rule-Load-Reihenfolge: UEBA-File wird vor den Parent Rules geladen
Wazuh lädt Rule-Files in der Praxis so, dass die Reihenfolge im Ruleset entscheidend ist. Liegt das UEBA-File im Verzeichnis so, dass es vor dem Trellix-DLP-File eingelesen wird, werden Regeln mit if_sid/if_matched_sid zwar syntaktisch akzeptiert, aber ihre Abhängigkeiten sind zu diesem Zeitpunkt noch nicht verfügbar.
Typischer Effekt:
- UEBA-Regeln werden „zu früh“ geladen
- Parent Rules existieren noch nicht im Regelbaum
- Ergebnis: Kein Triggering wie erwartet
Genau deswegen funktioniert 106201 sofort, wenn sie im selben File unterhalb der Parent Rules steht: Dann ist die Auswertungs- und Abhängigkeitskette garantiert konsistent.
3) Nebenbaustellen: UEBA-Korrelation hängt an stabilen Feldern
Die Korrelation nutzt:
<same_field>additionalInformation.Sender</same_field>
Das ist grundsätzlich sinnvoll, aber nur dann stabil, wenn:
- das Feld in allen Events existiert,
- die Schreibweise identisch ist (inkl. Leerzeichen/Format),
- der Wert nicht variiert (z. B. „Name<mail>“ vs. „Name <mail>“).
In den Beispielen ist der Sender-String vorhanden und konsistent genug – das Hauptproblem liegt hier eindeutig bei Load-Order und Integration-Matching.
Lösung / Best Practices
Schritt 1: Base Rule auf tatsächliche integration anpassen
Wenn die Logs Laurus_Trellix_DLP liefern, muss die Base Rule exakt darauf matchen – oder per Regex/Alternativen bewusst mehrere Integrationen zulassen.
Beispiel (exakt passend):
<rule id="118100" level="0">
<decoded_as>json</decoded_as>
<field name="integration">Laurus_Trellix_DLP</field>
<description>Trellix DLP: Base Alert</description>
</rule>
Wenn mehrere Tenants/Integrationen existieren, dann lieber konsolidiert über ein Pattern (sofern eure Naming-Konvention das erlaubt), z. B. per Regex-Alternative in einem sauberen Namensschema.
Schritt 2: Rule-Load-Reihenfolge erzwingen (empfohlen)
Die pragmatischste Lösung ist, die Dateinamen so zu gestalten, dass Parent Rules immer vor Child/UEBA Rules geladen werden. In der Praxis hat sich bewährt:
rules-trellix-DLP-*.xml(Parent)rules-ueba-*.xml(Child/UEBA)
Damit liegt die UEBA-Datei alphabetisch hinter der DLP-Datei und wird später geladen. Genau dieses Vorgehen ist in Tests typischerweise sofort erfolgreich.
Beispiel:
- vorher:
UEBA-rules-nopalcyber.xml(wird ggf. früh geladen) - nachher:
rules-ueba-nopalcyber.xml(wird nach DLP geladen)
Schritt 3: UEBA-Regeln bewusst „unter“ die Klassifizierung hängen
Für UEBA ist es sauberer, nicht auf die Base Rule (118100), sondern auf die klassifizierte Rule (118101) zu hängen – so wie im Beispiel. Wichtig ist nur: 118101 muss garantiert feuern können (Integration + Severity korrekt).
Schritt 4: Korrelation testen – immer mit wazuh-logtest
Beim Testen sollte man nicht nur „kommt Alert ja/nein“ prüfen, sondern die Phasen lesen:
- Phase 2: Sind die Felder wirklich so decodiert, wie die Rules erwarten?
- Phase 3: Welche Rule-ID feuert tatsächlich?
Wenn wazuh-logtest nach der Umbenennung und Integration-Korrektur 106201 als „Alert to be generated“ ausgibt, ist die Basis belastbar. Danach erst lohnt es sich, 106202 (frequency/timeframe) zu testen.
Schritt 5: Korrelation robust machen (optional, aber sinnvoll)
Wenn additionalInformation.Sender formatbedingt schwankt, empfiehlt sich:
- ein stabileres Feld (z. B.
eventUserDetails.userAccount,userPrincipalName,userEmail), sofern vorhanden und korrekt gefüllt, - oder eine Normalisierung im Ingest (z. B. per Pipeline/Integration), bevor Wazuh die Rule-Auswertung macht.
Lessons Learned / Best Practices
- Rule-Abhängigkeiten sind nicht „dateiunabhängig“. Sobald
if_sid/if_matched_sidüber Files hinweg verwendet wird, muss die Load-Reihenfolge deterministisch sein. - Dateinamen sind Betriebslogik. In produktiven Wazuh-Setups ist das Naming-Schema der Rules kein Kosmetikthema, sondern ein Stabilitätsfaktor.
- Integration-Felder sind Single-Point-of-Failure. Ein falscher
integration-String killt die gesamte Regelkette – deshalb sollte man ihn bei neuen Feeds als erstes im Decoder-Output validieren. - UEBA zuerst klassifizieren, dann korrelieren. Parent Rules sollten den Eventtyp und die Severity sauber kategorisieren; UEBA-Regeln hängen dann an diesen stabilen „Labels“.
- Tests immer mit echten Payloads. „Sanitized logs“ sind okay, aber Änderungen an Schlüsseln wie
integrationoder an der Feldstruktur sind kritisch und müssen 1:1 den Produktionspayload abbilden.
Fazit
Wenn UEBA-Regeln in Wazuh „nicht triggern“, obwohl der Rule-Code korrekt wirkt, liegt die Ursache oft nicht in frequency oder same_field, sondern in der Basis: matcht die Parent Rule überhaupt – und wird sie vor den UEBA-Regeln geladen?
Im gezeigten Trellix-DLP-JSON-Szenario lösen zwei Maßnahmen das Problem zuverlässig: integration an den tatsächlichen Payload anpassen und die Rule-Load-Reihenfolge über konsistentes File-Naming (oder Ruleset-Order) sicherstellen. Danach funktionieren sowohl die Einzelerkennung (106201) als auch die Korrelation (106202) stabil und nachvollziehbar.
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/p1767709776647239