Wazuh-UEBA-Regeln auf JSON-Integrationen: Warum Abhängigkeiten über mehrere Rule-Files oft „nicht triggern“

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-Klassifizierung
  • UEBA-rules-nopalcyber.xml: UEBA-Regeln, die auf den Parent Rules aufsetzen

Beispielaufbau (vereinfacht):

Base Rule

  • 118100: matcht auf JSON + integration
  • 118101: klassifiziert Minor/Warning

UEBA

  • 106201: matcht auf 118101 und generalDetails.incidentType = Email Protection
  • 106202: korreliert Wiederholungen: frequency="3" in timeframe="43200" (12h) pro additionalInformation.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 integration oder 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