Einleitung
SSH-Authentifizierungslogs sind eine zentrale Datenquelle für die Angriffserkennung in Wazuh. Gerade bei fehlgeschlagener Schlüssel-Authentifizierung („key-based auth required“) liefern sshd-Logs wichtige Hinweise auf Fehlkonfigurationen oder gezielte Angriffsversuche.
Damit diese Ereignisse zuverlässig in Regeln verarbeitet werden können, ist eine korrekte Decoder-Strategie entscheidend – insbesondere bei lokalen Anpassungen.
Dieser Artikel basiert auf einem realen Community-Fall und zeigt praxisnah, warum ein funktionierender Custom-Decoder scheinbar ignoriert wird, wie Decoder-Priorität tatsächlich funktioniert und wie die finale, saubere Lösung als Decoder und Regel aussieht.
Ausgangslage / Problemstellung
Ein Linux-Server erzeugt folgendes SSH-Log:
Jan 16 16:05:33 serverX sshd[3511748]: Disconnected from authenticating user smith 10.200.1.10 port 48262 [preauth]
Ziel ist es, für dieses Ereignis:
srcuser = smithsrcip = 10.200.1.10
zu extrahieren, um darauf basierend eine eigene Regel zu schreiben.
Der aktuelle Zustand in wazuh-logtest:
**Phase 2: Completed decoding.
name: 'sshd'
srcip: '10.200.1.10'
srcuser fehlt. Ein Custom Decoder wird erstellt und unter/var/ossec/etc/decoders/local_decoder.xml abgelegt – hat aber keine Wirkung.
Wird derselbe Decoder testweise in die Standarddatei 0310-ssh_decoders.xml verschoben, funktioniert er sofort.
Technische Analyse
Der erste Decoder-Versuch (korrekt – aber wirkungslos)
Der initiale Custom Decoder sah wie folgt aus:
<decoder name="sshd-disconnect-preauth">
<parent>sshd</parent>
<prematch>^Disconnected from authenticating user \.*[preauth]$</prematch>
<regex> from authenticating user (\S+) (\S+) </regex>
<order>srcuser,srcip</order>
</decoder>
Logisch korrekt, syntaktisch valide – aber im Betrieb ignoriert.
Die eigentliche Ursache: ein alter, vergessener Child-Decoder
Durch gezielte Suche stellte sich heraus, dass bereits ein anderer Custom Child-Decoder für sshd existierte, ebenfalls unter /var/ossec/etc/decoders/:
<decoder name="sshd-ip">
<parent>sshd</parent>
<prematch> port </prematch>
<regex offset="after_parent">\.* (\d+.\d+.\d+.\d+) port</regex>
<order>srcip</order>
</decoder>
Dieser Decoder matcht sehr früh und extrahiert ausschließlich srcip.
Entscheidende Erkenntnis zur Decoder-Logik
Das beobachtete Verhalten bestätigt eine zentrale Regel der Wazuh-Decoder-Engine:
- Normale Child-Decoder:
→ Der erste passende Child-Decoder unter einem Parent beendet die Auswertung aller weiteren Child-Decoder. - Sibling Decoders (Sonderfall):
→ Mehrere Decoder mit demselben Namen wie der Parent können nacheinander matchen und Felder kumulativ extrahieren.
Im vorliegenden Fall war sshd-ip der erste passende Child-Decoder – dadurch wurde sshd-disconnect-preauth nie mehr ausgewertet.
Lösung / Best Practices
Lösung 1: Reihenfolge der Child-Decoder korrigieren (minimal-invasiv)
Die einfachste und saubere Lösung bestand darin, beide Custom Decoder in einer Datei zu halten und den spezifischeren Decoder zuerst zu definieren:
<!--
Jan 16 16:05:33 serverX sshd[3511748]: Disconnected from authenticating user smith 10.200.1.10 port 48262 [preauth]
-->
<decoder name="sshd-disconnect-preauth">
<parent>sshd</parent>
<prematch>^Disconnected from authenticating user</prematch>
<regex>Disconnected from authenticating user (\S+) (\S+) port</regex>
<order>srcuser,srcip</order>
</decoder>
<decoder name="sshd-ip">
<parent>sshd</parent>
<prematch> port </prematch>
<regex offset="after_parent">\.* (\d+.\d+.\d+.\d+) port</regex>
<order>srcip</order>
</decoder>
Ergebnis in wazuh-logtest:
**Phase 2: Completed decoding.
name: 'sshd'
parent: 'sshd'
srcuser: 'smith'
srcip: '10.200.1.10'
Damit ist das Problem vollständig gelöst – ohne Änderungen an Stock-Dateien.
Alternative: Sibling-Decoders (für variable SSH-Formate)
Wenn mehrere SSH-Logformate schrittweise dekodiert werden sollen, ist der Einsatz von Sibling Decoders robuster:
<decoder name="sshd">
<program_name>^sshd</program_name>
</decoder>
<decoder name="sshd">
<parent>sshd</parent>
<regex>Disconnected from authenticating user (\S+)</regex>
<order>srcuser</order>
</decoder>
<decoder name="sshd">
<parent>sshd</parent>
<regex>(\d+\.\d+\.\d+\.\d+)</regex>
<order>srcip</order>
</decoder>
Hier tragen mehrere Decoder gemeinsam zur Feldextraktion bei. Diese Methode ist besonders hilfreich bei uneinheitlichen Logstrukturen.
Beispielregel auf Basis des neuen Decoders
Sobald srcuser und srcip zuverlässig extrahiert werden, kann eine eigene Regel definiert werden, z. B.:
<rule id="100200" level="6">
<if_matched_sid>sshd</if_matched_sid>
<field name="program_name">sshd</field>
<match>Disconnected from authenticating user</match>
<description>
SSH key-based authentication failed for user $(srcuser) from $(srcip)
</description>
<mitre>T1110</mitre>
</rule>
Diese Regel eignet sich für:
- Fehlkonfigurierte Clients ohne gültigen SSH-Key
- Frühe Erkennung von gezielten SSH-Zugriffsversuchen
- Ergänzung bestehender Brute-Force-Logik
Lessons Learned / Best Practices
- Ein „ignorierter“ Decoder ist fast immer ein Prioritäts- oder Konfliktproblem, kein Syntaxfehler.
- Alte Custom Decoder können Jahre später neue Anpassungen aushebeln – regelmäßige Inventur ist essenziell.
- Spezifische Decoder vor generischen platzieren.
- Für komplexe oder variable Logs sind Sibling Decoders die nachhaltigere Strategie.
- Stock-Dateien niemals direkt ändern – lokale Decoder und saubere Reihenfolge reichen fast immer aus.
Fazit
Der Fall zeigt exemplarisch, dass Wazuh-Decoder nicht linear, sondern regelbasiert mit klarer Priorität arbeiten. Sobald ein Child-Decoder greift, endet die Auswertung – außer bei bewusst eingesetzten Sibling-Decoders.
Wer dieses Prinzip versteht und gezielt nutzt, kann selbst komplexe SSH-Logformate stabil dekodieren und darauf präzise, hochwertige Security-Regeln aufbauen.
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/p1768585000518089