Wazuh 4.7 → 4.14: Warum SMTP-Multiline-Logs „zerfallen“ und Decoder nur noch die erste Zeile sehen

Einleitung

Beim Upgrade von Wazuh-Versionen fallen Decoder-Probleme oft erst im laufenden Betrieb auf: Regeln triggern nicht mehr, Felder bleiben leer oder es wird nur noch ein Bruchteil des erwarteten Events extrahiert. Ein besonders häufiger Auslöser ist nicht der Decoder selbst, sondern die Art, wie Wazuh Logzeilen zu Events gruppiert. Multiline-Formate (z. B. SMTP-Session-Traces) sind dafür prädestiniert: Wenn die Event-Grenzen nicht mehr korrekt erkannt werden, „sieht“ der Decoder nur die erste Zeile – und der Rest der Session geht als separate Einzel-Events verloren oder wird verworfen.

Ausgangslage / Problemstellung

In einer Umgebung mit SMTP-Logs, die als Block/Session über mehrere Zeilen geschrieben werden, funktionierten benutzerdefinierte Decoder in Wazuh 4.7 wie erwartet. Nach dem Upgrade auf Wazuh 4.14 werden plötzlich nur noch einzelne Felder extrahiert – konkret scheint nur noch eine Zeile (z. B. „connected at …“) zuverlässig anzukommen.

Beispielhafter Logblock:

  • Startzeile mit Marker smtpLog: #
  • danach viele Zeilen derselben Session (EHLO, MAIL FROM, RCPT TO, DATA, Greylisting, disconnected …)

Der vorhandene Decoder-Stack basiert auf einem prematch auf ^smtpLog: und mehreren Child-Decodern mit PCRE2-RegEx zur Feldextraktion.

Symptom:

  • Früher: Mehrere Felder (srcip, mail_from, rcpt_to, country, ehlo …) wurden gefüllt.
  • Jetzt: Nur noch ein einzelnes Feld wird extrahiert (typisch aus einer einzelnen Zeile) – der Rest bleibt leer.

Technische Analyse

1) Decoder vs. Eventbildung: Der entscheidende Unterschied

Wazuh-Decoder arbeiten pro Event (pro „Logeintrag“, so wie er dem Analysisd übergeben wird). Bei Multiline-Logs ist daher nicht der Decoder der Engpass, sondern die Event-Gruppierung im Log-Collector (logcollector).

Wenn der Collector jeden Zeilenumbruch als neues Event interpretiert, passiert Folgendes:

  • Das prematch ^smtpLog: matcht nur auf die erste Zeile (z. B. smtpLog: #).
  • Alle Folgezeilen beginnen mit Timestamp/Bracket-Mustern (15:40:44.004 [IP]...) und matchen nicht gegen ^smtpLog:.
  • Ergebnis: Child-Decoder laufen nur dann, wenn die jeweilige Zeile als Event überhaupt den Parent-Prematch erfüllt (oder wenn der Parent in einer Session-Reassembly existiert). Sobald die Blockbildung wegfällt, „zerbricht“ die gesamte Decoder-Kaskade.

Dass „connected date/time“ noch kommt, ist ein typischer Zufallseffekt, wenn diese Information (je nach tatsächlichem Ingest) noch im selben Event landet oder ein Teil des Blocks anders zusammengefügt wird. Für zuverlässige Feldextraktion muss der gesamte Block als ein einziges Event an den Decoder übergeben werden.

2) Was sich beim Upgrade faktisch ändert

Wazuh entwickelt Collector/Parsing kontinuierlich weiter. Schon kleine Änderungen am Default-Verhalten oder an der File-Read-Logik können dazu führen, dass Multiline-Blöcke nicht mehr automatisch zusammengefasst werden – insbesondere wenn vorher „zufällig“ das gewünschte Verhalten entstand (z. B. durch Buffering oder Logrotation-Verhalten). Der Decoder ist dann unverändert korrekt, bekommt aber nicht mehr denselben Input.

3) Typische Stolpersteine bei Multiline-Logs

  • Start-of-Event nicht eindeutig: Ohne klaren Startmarker kann Wazuh Blöcke nicht korrekt segmentieren.
  • Zeilen beginnen nicht mit dem Prematch: Der Parent-Decoder ist zu strikt, wenn die Blockbildung fehlt.
  • Regex auf \s...: Viele Child-RegEx erwarten Kontext über Zeilengrenzen. Wenn der Event nur eine Zeile ist, matchen sie nicht.
  • Duplizierte Decoder-Namen: In dem Beispiel existiert smtp_log_sender_email zweimal. Das kann zu Überschreibungen/unerwartetem Verhalten führen (auch wenn es früher „ging“, ist es ein Risiko – spätestens bei Updates, die strikter validieren oder das Load-Order-Verhalten ändern).

Lösung / Best Practices

Schritt 1: Multiline-Eventbildung im ossec.conf aktivieren

Der robuste Fix ist, die Logquelle als Multiline-Quelle zu konfigurieren, sodass Wazuh den gesamten SMTP-Block als ein Event an die Decoder weitergibt.

Beispiel:

<localfile>
  <log_format>multi-line-regex</log_format>
  <location>/path/to/your/smtp.log</location>
  <multiline_regex>^smtpLog:</multiline_regex>
</localfile>

Wirkung:

  • multi-line-regex aktiviert Blockbildung.
  • multiline_regex definiert, welche Zeile einen neuen Block startet.
  • Alles nach smtpLog: bis zum nächsten smtpLog: wird als ein Event verarbeitet.

Damit greifen die bestehenden Parent/Child-Decoder wieder konsistent, weil prematch und Child-RegEx den kompletten Kontext bekommen.

Schritt 2: Decoder auf „Multiline-Input“ härten

Wenn der Block nun als ein Event kommt, sollten Child-RegEx grundsätzlich damit umgehen können, dass im Payload Zeilenumbrüche enthalten sind. PCRE2 in Wazuh kann das, aber zwei Best Practices helfen:

  • RegEx so formulieren, dass sie nicht ungewollt an Zeilenanfängen scheitert.
  • Für Felder, die in unterschiedlichen Zeilen vorkommen können, ggf. explizit auf Zeileninhalt matchen statt auf Position.

Beispiel (konservativ, robust):

  • IP: eher auf IPv4-Muster matchen als auf \s(\[\d*.\d*.\d*.\d*])\D (Punkte sind in RegEx ohne Escaping „beliebiges Zeichen“).
    • Besser: \[(\d{1,3}(?:\.\d{1,3}){3})\]

Schritt 3: Decoder-Namenskollisionen beseitigen

Im Rohmaterial ist smtp_log_sender_email doppelt definiert. Das sollte bereinigt werden:

  • Decoder eindeutig benennen, z. B.:
    • smtp_log_sender_email_1
    • smtp_log_sender_email_2

Zusätzlich die RegEx selbst prüfen: senderEmail\D2\D\D\s(...) wirkt sehr fragil (abhängig von exakt diesem Token). Stabiler ist meist ein Muster, das die Zahl optional macht, z. B. senderEmail(?:\(\d+\))?:\s(...) oder passend zum echten Logformat.

Schritt 4: Test- und Validierungsworkflow

Nach Anpassung:

  1. Wazuh Manager neu laden/restarten (je nach Setup).
  2. Mit einem Testlog sicherstellen, dass im Event wirklich der komplette Block ankommt (z. B. in archives.json / alerts.json prüfen).
  3. Erst dann Decoder-RegEx verfeinern, bis alle gewünschten Felder zuverlässig extrahiert werden.

Wichtig: Wenn der Block korrekt als ein Event ankommt, sind Decoder-Fixes schnell und deterministisch. Wenn nicht, „debuggt“ man endlos an Decodern herum, obwohl die Ursache die Eventbildung ist.

Lessons Learned / Best Practices

  • Multiline immer an der Quelle lösen: Decoder reparieren keine Event-Grenzen. Für sessionbasierte Logs (SMTP, SSH-Handshake-Traces, App-Stacks) ist multi-line-regex die zuverlässigste Basis.
  • Prematch so wählen, dass er wirklich den Eventanfang markiert: Ein eindeutiger Startmarker (wie smtpLog:) ist ideal.
  • RegEx nicht unnötig fragil gestalten: Insbesondere IP-Patterns und „Trennzeichen“-Muster (\D, \W) sollten bewusst eingesetzt werden; ansonsten matcht es zwar „irgendwie“, aber nicht stabil.
  • Eindeutige Decoder-Namen: Doppelte Namen sind eine Wartungsfalle und können je nach Load-Order zu nicht reproduzierbarem Verhalten führen.
  • Upgrades mit Parser-/Collector-Checks begleiten: Nach Version-Sprüngen immer zuerst prüfen: Kommen Events strukturell gleich an (Blockbildung, log_format, location, Rotation)?

Fazit

Wenn SMTP-Multiline-Logs nach einem Upgrade nur noch zeilenweise ankommen, liegt das Problem in der Praxis fast immer an der Event-Gruppierung im Logcollector – nicht daran, dass der Decoder „plötzlich anders“ wäre. Die stabile Lösung ist, die Logquelle in ossec.conf auf multi-line-regex umzustellen und ^smtpLog: als Startmarker zu definieren. Danach funktionieren bestehende Parent/Child-Decoder wieder erwartbar, und verbleibende Anpassungen beschränken sich auf saubere, robuste RegEx und eindeutige Decoder-Namen.

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/C07CCCCGHHP/p1769411663992639