Einleitung
Systemzustände per Command-Ausführung zu überwachen (Ports, Kernel-Flags, Prozesse, eBPF-Settings) ist in Wazuh ein etabliertes Muster – aber die Plattform bietet dafür zwei unterschiedliche Wege, die sich im Datenfluss, in der Standardauswertung und in der Alert-Erzeugung deutlich unterscheiden. Wer beides vermischt, stolpert schnell über scheinbar „verschwundene“ Events, fehlende Archive-Einträge oder Ausgaben, die unerwartet zeilenweise als einzelne Events ankommen.
Dieser Artikel ordnet die beiden Methoden technisch ein, erklärt, warum der Command-Wodle ohne passende Decoder/Rules „still“ bleibt, wie du das tag-Feld sinnvoll für Decoder und Regeln nutzt – und warum Multi-Line-Output beim Wodle als mehrere Events erscheint (inklusive praktikabler Gegenmaßnahmen).
Ausgangslage / Problemstellung
Es existieren zwei Konfigurationen auf Agent-Seite:
1) Logcollector über <localfile> mit full_command
Beispiel: netstat -tulpn alle 360 Sekunden, Ausgabe wird vollständig geloggt.
2) Command-Wodle über <wodle name="command">
Beispiel: cat /proc/sys/kernel/unprivileged_bpf_disabled alle 2 Minuten mit tag, run_on_start, ignore_output=no.
Offene Fragen:
- Muss beim Command-Wodle zwingend ein eigener Decoder und eine eigene Rule existieren, sonst sieht man gar nichts (auch nicht in den Archives)?
- Kann man das
tag-Feld im Decoder nutzen? - Warum wird die Ausgabe beim Command-Wodle in mehrere Events (eine Zeile = ein Event) gesplittet, und gibt es einen Parameter, der „alles in ein full_log“ zwingt?
Technische Analyse
1) Unterschiedliche Datenpfade und Standardverhalten
<localfile> / Logcollector (full_command)
Der Logcollector ist primär fürs Einsammeln von Logs gebaut, kann aber auch Commands ausführen. Wazuh kennt diesen Kanal seit langem und hat dafür einen eingespielten Standardpfad inkl. Basiserkennung. Ob daraus Alerts entstehen, hängt dann von Rules ab, aber die Rohdaten landen in der Regel zuverlässig im Logfluss. Die <localfile>-Sektion ist in der Referenz explizit als Mechanismus für Dateien, Windows-Events und Command-Output beschrieben.
<wodle name="command"> / Command module
Der Command-Wodle ist die „moderne“ Variante und bietet zusätzliche Sicherheits- und Betriebsmerkmale wie optionale Checksummen-Verifikation (MD5/SHA1/SHA256), flexible Scheduling-Optionen und definierte Timeouts. Das ist in der Wodle-Referenz dokumentiert.
Der wichtige Punkt: Für sinnvolle Alerting-Auswertung ist beim Command-Wodle typischerweise ein passendes Ruleset nötig, weil die Ausgabe semantisch ausgewertet werden muss. Wazuhs „Command output analysis“-Doku beschreibt explizit den Ablauf: Decoder extrahieren Felder, danach matchen Rules, um Alerts zu erzeugen.
2) „Sehe ich ohne Decoder/Rules gar nichts – nicht einmal in Archives?“
Hier muss man sauber trennen:
- Alerts entstehen nur, wenn eine Rule matcht (häufig auf Feldern aus einem Decoder). Das ist beim Command-Wodle der Normalfall: Ohne Rule kein Alert, ohne Decoder fehlen oft die Felder für Rule-Conditions.
- Archive-Index / Archivierung hängt davon ab, wie deine Umgebung Archivierung konfiguriert (Manager-seitig) und ob Events vom Agent überhaupt als Events beim Manager ankommen. In der Praxis wirkt es „wie nichts“, wenn:
- keine Rule matcht (kein Alert sichtbar),
- und gleichzeitig die Archivierung/Indexierung nicht so konfiguriert ist, dass ungeparste Events komfortabel im Dashboard auffindbar sind.
Für eine belastbare Betriebsstrategie gilt daher: Plane beim Command-Wodle immer Decoder + Rule (oder strukturiere Output so, dass du mit Minimal-Regeln arbeiten kannst).
3) Kann man tag im Decoder verwenden?
Ja – das tag ist ein zentrales Klassifizierungsmerkmal des Command-Wodle („Descriptive name for the command“). Es ist ausdrücklich als Konfigurationsparameter dokumentiert und wird typischerweise genutzt, um Decoder/Rules auf genau diesen Command-Kanal zu verankern (z. B. „ebpf_check“).
Best Practice ist: tag als stabilen Anker nutzen (statt z. B. auf volatile Command-Ausgaben zu prematchen) und daraus eigene Decoder-/Rule-Gruppen ableiten.
4) Warum wird Wodle-Output in Zeilen gesplittet – und kann man das abschalten?
Das Zeilen-Splitting ist ein bekanntes, intendiertes Verhalten der Command-Ausgabe: Der Output wird in einzelne Zeilen getrennt und als separate Events verarbeitet. In einem langjährigen Issue wird genau das als Eigenschaft des Moduls beschrieben („splits the output into lines“), inkl. Hinweis, dass es keine Option gibt, Zeilen wieder zusammenzuführen oder nach Delimiter zu splitten.
Damit ist auch klar: Einen „keep output in one full_log“-Parameter wirst du im Command-Wodle nicht finden, weil das Modul so konzipiert ist.
Lösung / Best Practices
A) Entscheidungshilfe: Wann <localfile full_command> und wann <wodle command>?
Nutze <wodle name="command">, wenn du:
- klare Scheduling- und Timeout-Kontrolle brauchst,
- Skripte/Binaries gegen Manipulation prüfen willst (verify_md5/sha*),
- Commands standardisiert mit
tagklassifizieren möchtest.
Nutze <localfile log_format=full_command>, wenn du:
- „einfach nur Output einsammeln“ willst und dich mit den vorhandenen Standardpfaden wohler fühlst,
- schnell erste Ergebnisse im Logfluss sehen willst (auch ohne sofort perfektes Decoding),
- bestehende Rule-Hierarchien auf Basis des Command-Outputs fortführen möchtest.
Wichtig: Beide Wege sind legitim – entscheidend ist, ob du strukturiertes Alerting (wodle) oder schnellen „rohlog“-Zugriff (localfile) priorisierst.
B) Command-Wodle so bauen, dass du ohne Multi-Line-Probleme auskommst
Da der Wodle Output zeilenweise Events erzeugt, solltest du Commands so gestalten, dass sie pro Ausführung genau eine Zeile liefern – oder strukturiert als Single-Line JSON.
Praktische Patterns:
- Single-Line-Ausgabe erzwingen
Beispiele:
tr '\n' ' 'oderpaste -sd ' ' -um Zeilen zu einer Zeile zu machen- bei Tools wie
netstat,ss,iptableslieber gezielt filtern/aggregieren statt „alles“
- JSON als Einzeiler ausgeben
Schreibe ein kleines Wrapper-Skript, das Messwerte als JSON in einer Zeile ausgibt (z. B.{ "tag":"ebpf_check","unprivileged_bpf_disabled":1 }). Damit kannst du in Wazuh sehr stabil decodieren (JSON-Decoder) und Rules sauber formulieren. Wazuhs Decoder-Doku betont den Nutzen strukturierter Formate und den Decoder/Rule-Match-Prozess. - Komplexe, mehrzeilige Befunde nicht „negieren“, sondern normalisieren
Wenn du eigentlich „negation filter“ über den gesamten Output brauchst (z. B. „kein Prozess X läuft“), dann ist es operational deutlich robuster, die Logik ins Skript zu ziehen und nur das Ergebnis zu emitten (OK/FAIL plus Kontext) – statt in Wazuh über viele Einzelevents eine globale Negation zu modellieren.
C) Decoder/Rules für Command-Wodle minimal und robust aufsetzen
Ein bewährtes Muster:
- Decoder anchored über
tag(Beispiel-Name frei wählbar)
- Parent matcht auf den Tag
- Child extrahiert die Nutzlast (oder JSON)
- Rule:
<decoded_as>auf den Parent- Bedingungen auf Felder oder raw payload
Das folgt dem in der „Command output analysis“-Doku beschriebenen Grundprinzip: Erst decodieren, dann per Rule Alert auslösen.
D) Wenn du Multi-Line trotzdem brauchst: bewusst „pro Zeile“ designen
Manchmal ist es sinnvoll, jede Zeile als Event zu bekommen (z. B. „jede offene Portzeile ist ein Finding“). Dann solltest du:
- Zeilenformat deterministisch machen (z. B.
ss -tulpnHohne Header), - Decoder so bauen, dass eine Zeile genau einen Datensatz ergibt,
- Rules pro Datensatz bewerten (statt „den ganzen Dump“).
Das funktioniert sehr gut – du musst nur akzeptieren, dass Wodle keine „Batch semantics“ liefert.
Lessons Learned / Best Practices
- Command-Wodle ist nicht „plug and play“ für Alerts: Ohne passende Rules bleibt es still; ohne Decoder fehlen oft die Felder für Rules.
tagist der Schlüssel zur sauberen Klassifizierung: Nutze es als stabilen Anker für Decoder/Rule-Gruppen, statt auf fragilen Output zu prematchen.- Multi-Line-Output ist erwartetes Verhalten: Der Output wird zeilenweise in Events zerlegt; es gibt keinen Schalter, um alles als einen Event zu behalten.
- Normalisiere Output upstream: Für Negationen/„Gesamtzustand“-Checks ist ein Wrapper-Skript, das eine Zeile (oder JSON) ausgibt, fast immer die sauberste Lösung.
- Wähle das Modul nach Zielbild: „Rohdaten schnell sehen“ →
<localfile full_command>; „strukturierte Checks mit Scheduling/Verifikation“ →<wodle command>.
Fazit
<localfile> und <wodle name="command"> lösen ähnliche Aufgaben, sind aber unterschiedlich gedacht: Der Logcollector ist ein pragmatischer Einsammler, der Command-Output wie Logs behandelt; der Command-Wodle ist ein kontrollierter, sicherheitsorientierter Executor, der für sauberes Alerting in der Praxis ein Ruleset (und oft Decoder) braucht. Das „Zeile = Event“-Verhalten des Wodle ist dabei kein Bug, sondern Design – und die beste Gegenmaßnahme ist, die Ausgabe upstream zu normalisieren (Single-Line/JSON) oder bewusst pro Zeile zu dekodieren.
Quellenverweise (Copy & Paste)
- https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/wodle-command.html
- https://documentation.wazuh.com/current/user-manual/capabilities/command-monitoring/command-output-analysis.html
- https://documentation.wazuh.com/current/user-manual/capabilities/command-monitoring/configuration.html
- https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/localfile.html
- https://github.com/wazuh/wazuh/issues/2712
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/p1770991699099859