Wazuh: Windows-Noise rausfiltern – saubere Suppression für normale Logons

Wer mit Windows-Events in Wazuh arbeitet, landet früher oder später hier:
Die Konsole ist voll mit ganz normalen, technischen Logons, vor allem Event ID 4624 (Logon Success) – z. B. Service-Logons über services.exe.
Kein Angriff, kein Risiko – aber jede Menge Lärm.

Genau das wollte Kashif in seinem Test-Setup lösen:
„Wie unterdrücke ich nur diese Routine-Logons, ohne andere Logon-Events zu verlieren?“

Schauen wir uns an, was schiefgelaufen ist – und wie die finale, funktionierende Lösung aussieht.

Ausgangspunkt: sinnvoller Ansatz, aber falsche Feldnamen

Kashif startete mit einer eigenen Regel, die eine sehr spezifische Kombination abfangen sollte:

  • Windows Logon Success (if_sid 60106)
  • Event ID 4624
  • Logon Type 5 (Service Logon)
  • Auth-Package Negotiate
  • Logon Process Advapi
  • Process Name C:\Windows\System32\services.exe

Die Idee war exakt richtig:
einen vorhandenen Standard-Alarm (60106) „verfeinern“ und in diesem Spezialfall stummschalten.

Sein erster Versuch sah so aus (vereinfacht):

<group name="windows,windows_security,authentication_success,">
  <rule id="100002" level="0">
    <if_sid>60106</if_sid>
    <field name="data.win.system.eventID">4624</field>
    <field name="data.win.eventdata.logonType">5</field>
    <field name="data.win.eventdata.authenticationPackageName">Negotiate</field>
    <field name="data.win.eventdata.logonProcessName">Advapi</field>
    <field name="data.win.eventdata.processName">C:\\\\Windows\\\\System32\\\\services\.exe</field>
    <description>Ignore normal service logons (SYSTEM via services.exe using Advapi/Negotiate)</description>
    <options>no_full_log</options>
  </rule>
</group>

Problem:
In Wazuh-Regeln heißen die Felder nicht data.win.…, sondern z. B.:

  • win.system.eventID
  • win.eventdata.logonType
  • usw.

data. siehst du später im Index (z. B. in OpenSearch/Kibana), aber für den Regel-Parser gilt die Struktur aus archives.json bzw. aus dem Decoder – und dort sind die Feldnamen ohne data.

Erster Fix von Stuti: data. überall entfernen.

Zweiter Stolperstein: Regex & Backslashes

Im nächsten Schritt hakte es noch am Feld processName.

Im Alert sah das Feld so aus:

"processName": "C:\\\\Windows\\\\System32\\\\services.exe"

Das ist doppelt escaped, weil es durch mehrere Ebenen (JSON, Konsole, UI) ging.
In der Regel muss der Pfad so angegeben werden, wie er nach der Dekodierung vorliegt – und im Wazuh-Regel-Regex gelten eigene Regeln.

Kashifs Zwischenversion:

<field name="win.eventdata.processName" type="pcre2">(?i)^C:\\Windows\\System32\\services\.exe$</field>

Dazu zwei wichtige Punkte:

  1. Standard-Wazuh-Regex (ohne type="pcre2"):
    • . wird als Wildcard interpretiert
    • willst du einen echten Punkt matchen, darfst du ihn nicht escapen: <field name="somefield">program.exe</field>
    • program\.exe wäre hier falsch und würde programXexe etc. matchen
  2. Mit type="pcre2" gilt klassische PCRE2-Syntax
    → da ist program\.exe korrekt, wenn du einen Punkt literal willst.

Stuti ist einen Schritt einfacher gegangen und hat gar kein pcre2 benutzt, sondern die Literal-Variante sauber mit Backslashes angegeben.

Die funktionierende Version:

<group name="windows,authentication,service_logons">
  <!-- Suppress normal Windows service logons -->
  <rule id="100003" level="0">
    <if_sid>60106</if_sid>
    <field name="win.system.eventID">4624</field>
    <field name="win.eventdata.logonType">5</field>
    <field name="win.eventdata.authenticationPackageName">Negotiate</field>
    <field name="win.eventdata.logonProcessName">Advapi</field>
    <field name="win.eventdata.processName">C:\\\\Windows\\\\System32\\\\services.exe</field>
    <description>Ignore normal Windows service logons (SYSTEM via services.exe)</description>
    <options>no_full_log</options>
  </rule>
</group>

Warum vier Backslashes?

  • In XML schreibst du C:\\\\Windows...
  • Nach Parsing / Interpretation landet das beim Regex-Engine als C:\\Windows...
  • Und das entspricht dann einem Windows-Pfad mit einem Backslash.

Warum level="0" und if_sid?

Zwei wichtige Design-Entscheidungen der Regel:

1. if_sid 60106 – auf bestehende Logik aufbauen

Rule 60106 ist eine Standardregel im Wazuh-Ruleset:

Windows Logon Success

Sie triggert bereits korrekt auf erfolgreiche Windows-Logons.
Statt das Rad neu zu erfinden, nimmt Kashif:

<if_sid>60106</if_sid>

Damit sagt er:

„Nur Alerts, die bereits die 60106 ausgelöst haben, sollen nun zusätzlich meine Bedingungen matchen.“

Das ist sauber, robust und zukunftssicher, weil du der bestehenden Wazuh-Logik vertraust.

2. level="0" – komplett unterdrücken

level="0" bedeutet:

  • Kein Alert in wazuh-alerts-*
  • Kein Eintrag in der UI
  • Kein E-Mail-Alert (außer du überschreibst das explizit, was hier nicht der Fall ist)

So werden genau diese Routine-Service-Logons voll unterdrückt – alle anderen Logons (z. B. interaktiv, RDP, Netzwerk) bleiben weiterhin sichtbar.

Woher bekomme ich den „richtigen“ Raw-Log für meine Regel?

Kashif wollte wissen:

„Wie kommst du an genau den Log, den Wazuh intern benutzt? Event Viewer sieht anders aus.“

Antwort von Stuti:

  1. Archivierung aktivieren (auf Manager-Seite)
    In ossec.conf: <logall>yes</logall> <logall_json>yes</logall_json> (Achtung: mehr Storage-Verbrauch!)
  2. Logs anschauen: cat /var/ossec/logs/archives/archives.json | grep <keyword> Dort siehst du genau den JSON-Event, auf dessen Basis die Wazuh-Regeln arbeiten.
    Und daraus kannst du sauber Feldnamen wie win.eventdata.processName übernehmen.
  3. Regel mit wazuh-logtest testen
    So siehst du direkt, ob dein Regelwerk greift, bevor es live geht.

Zusätzlich hat Kevin Branch noch auf sein eigenes Toolset verwiesen, das speziell das Testen von Windows EventChannel-Logs gegen Wazuh-Regeln vereinfacht – ideal, wenn du öfter mit solchen Custom-Rules arbeitest.

Muster für eigene „Noise-Filter“-Regeln

Die Vorgehensweise aus diesem Beispiel kannst du generell nutzen, um andere Noise-Events zu reduzieren:

  1. Event identifizieren, das du unterdrücken willst
    – im Dashboard oder direkt aus archives.json.
  2. Standardregel finden, die darauf triggert
    → im Alert rule.id anschauen (z. B. 60106).
  3. Eigene Rule schreiben mit:
    • if_sid oder if_matched_sid auf diese ID
    • mehreren <field>-Bedingungen, um das Event sehr konkret einzugrenzen
      (ID, Typ, Prozess, User, etc.)
    • level="0" für vollständige Unterdrückung
      oder z. B. level="1" für „fast unsichtbar, aber noch suchbar“
  4. Regex-Syntax beachten
    • Standard-Regex ≠ PCRE2
    • Punkt, Backslashes, Anker (^, $) bewusst einsetzen
  5. Manager neu starten systemctl restart wazuh-manager
  6. Im Zweifel: mit wazuh-logtest und archives.json prüfen.

Fazit: Von „zu viel Noise“ zu „gezielt ruhiggestellt“

Ausgangssituation:
Das Dashboard war voll mit erfolgreichen, systeminternen Service-Logons, die niemanden interessieren, aber die Sicht auf echte Auffälligkeiten stören.

Durch:

  • korrekte Feldnamen (win.event* statt data.win.*),
  • saubere Regex für den Prozesspfad,
  • Nutzung der bestehenden Rule 60106 als Basis,
  • und level="0" zur vollständigen Unterdrückung

hat Kashif das Problem sauber gelöst – und nebenbei eine sehr gute Blaupause für weitere Suppression-Regeln gebaut.

https://wazuh.slack.com/archives/C0A933R8E/p1761898091851149

Mehr zu Wazuh …

Mehr zum Wazuh Ambassador Program …