Wazuh Custom Rules & Time-Based Detection: Warum die Syntax oft scheitert — und wie du es richtig machst

Daniel meldete ein Problem, das viele Wazuh-Nutzer kennen:
Beim Upload einer Custom Rule über das Dashboard erscheint nur:

Error 1113 – Syntax error in the rules file

Selbst wenn die Regel eigentlich harmlos aussieht.

In diesem Beitrag zeige ich:

  • warum die ursprüngliche Regel syntaktisch falsch war,
  • wie man häufige Fehler bei Custom Rules vermeidet,
  • warum <if_sid> oft falsch verwendet wird,
  • wie man Brute-Force Detection auf Windows korrekt implementiert,
  • und warum die Directive <time> keine mehrfachen Zeitbereiche zulässt.

Problem 1: Fehlerhafte Syntax bei Frequenz-Regeln

Die erste Regel des Users:

<rule id="100002" level="13">
    <decoded_as>windows_eventchannel</decoded_as>
    <if_sid>60106</if_sid>
    <frequency>5</frequency>
    <timeframe>60</timeframe>
    <same_field>srcip</same_field>
    <description>...</description>
</rule>

Was war falsch?

Fehler 1 — if_sid falsch eingesetzt

if_sid ist für eine einfache Regellogik.
Für Schwellenregeln mit frequency & timeframe muss man:

if_matched_sid verwenden

Fehler 2 — frequency & timeframe stehen falsch

Diese müssen als Attribute im <rule> geschrieben werden, nicht als separate Elemente.

Fehler 3 — Feldname falsch

Windows verwendet win.eventdata.ipAddress, nicht srcip.

So sieht die korrekte Regel aus

Jakub stellte die gültige Syntax bereit:

<rule id="100002" level="13" frequency="5" timeframe="60">
    <if_matched_sid>60106</if_matched_sid>
    <same_field>srcip</same_field>
    <description>...</description>
</rule>

Doch Hasitha wies auf einen wichtigen Punkt hin:

60106 ist die Logon Success-Regel

Wer Logon-Failures (Brute-Force) erkennen will, muss Rule 60105 nutzen – denn diese dekodiert Windows-Event 4625 („Logon Failed“).

Die finale, korrekte Brute-Force-Detection (Windows)

<group name="attempts,">
    <rule id="100999" level="13" frequency="5" timeframe="60">
        <if_matched_sid>60105</if_matched_sid>
        <same_field>win.eventdata.ipAddress</same_field>
        <description>Posible ataque de fuerza bruta: 5 intentos fallidos desde la misma IP en 1 minuto</description>
    </rule>
</group>

Aggregation von fehlgeschlagenen Loginversuchen
Innerhalb 60 Sekunden
Korrelation anhand der angreifenden IP

Problem 2: Syntaxfehler bei Zeitbereichen (Directive <time>)

Daniel wollte „außerhalb der Arbeitszeit“ erkennen und schrieb:

<time>00:00-07:00,20:00-23:59</time>

Das ist nicht erlaubt

Die Wazuh Directive <time> akzeptiert nur EINEN Zeitbereich.

Lösung: Zwei getrennte Regeln

<rule id="100540" level="12">
    <if_sid>5760</if_sid> <!-- SSH -->
    <group>after_hours,authentication</group>
    <time>20:00-23:59</time>
    <description>SSH acceso fuera de horario (20:00–23:59)</description>
    <options>alert_by_email</options>
</rule>

<rule id="100541" level="12">
    <if_sid>5760</if_sid>
    <group>after_hours,authentication</group>
    <time>00:00-07:00</time>
    <description>SSH acceso fuera de horario (00:00–07:00)</description>
    <options>alert_by_email</options>
</rule>

Für Windows gilt dasselbe – die SID (z. B. 18107 oder 60122) muss je nach Login-Typ angepasst werden.

Bonus: E-Mail-Alerts richtig setzen

Daniel verwendete:

<email_alert>yes</email_alert>

Das ist falsch.

In Wazuh heißt die Option:

<options>alert_by_email</options>

Global muss außerdem email_alert_level im Manager passen (Standard: ab Level 12).

Fazit

Dieser Thread zeigt, wie schnell kleine Syntaxdetails in Wazuh zu Fehler 1113 führen — und wie man es richtig macht:

  • if_matched_sid statt if_sid bei Frequency-Rules
  • frequency & timeframe als Rule-Attribute
  • richtige Windows-Felder verwenden (win.eventdata.ipAddress)
  • <time> erlaubt nur einen Bereich
  • E-Mail-Alerts: alert_by_email

Mit der finalen Version der Regeln laufen sowohl Brute-Force-Detektion als auch „Off-Hours“-Erkennung stabil und fehlerfrei.

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