Wazuh Decoder für UniFi CEF-Logs: Feld-Splitting, Formatabweichungen und Decoder-Konflikte sauber lösen

Einleitung

CEF (Common Event Format) ist ein etabliertes Log-Format mit einem festen Header (Version|Vendor|Product|…) und einer variablen Extension als Key-Value-Liste. Genau diese Mischung sorgt in Wazuh häufig für zwei typische Probleme: Decoder „catcht“ nicht zuverlässig (wegen leicht abweichender CEF-Header-Darstellung) oder Decoder kollidiert mit anderen CEF-Decodern (weil die Prematches zu generisch sind). CEF selbst ist als Header+Extension definiert, wobei die Extension aus Key-Value-Paaren besteht. OpenText+2OpenText+2

Dieser Beitrag zeigt anhand von Ubiquiti UniFi CEF-Logs, wie man Decoder so baut, dass sie (1) den CEF-Header robust parsen, (2) wichtige Extension-Felder extrahieren und (3) keine Konflikte mit anderen CEF-Quellen (z. B. Imperva/Incapsula) erzeugen.


Ausgangslage / Problemstellung

Es liegen UniFi-Logs im CEF-Format vor, u. a. in dieser Form:

2026-01-07T10:59:27+00:00 mmm-Up CEF: 0|Ubiquiti|UniFi Network|10.0.162|402|WiFi Client Roamed|1|UNIFIcategory=... UNIFIwifiName=Switch-up Workers ...

Der ursprüngliche Decoder verwendete:

  • einen sehr schmalen prematch auf CEF:0|Ubiquiti|UniFi Network (ohne Berücksichtigung von Leerzeichen nach CEF:),
  • Regex-Platzhalter wie (\.) / (\.+) (praktisch „Punkt(e)“, nicht „beliebige Zeichen“),
  • und erzeugte in der weiteren Iteration Konflikte mit einem anderen CEF-Decoder (Imperva), weil die Erkennung nicht sauber voneinander getrennt war.

Technische Analyse

1) CEF ist nicht immer „CEF:0|…“ – Whitespace und Syslog-Header verändern das Matching

Viele Geräte/Forwarder liefern CEF nicht als reinen String CEF:0|…, sondern mit einem Präfix (Timestamp/Hostname) und teilweise als CEF: 0|… (mit Leerzeichen). In Wazuh werden bei syslog-artigem Header in der Pre-Decoding-Phase Felder wie timestamp, hostname und program_name extrahiert. Wazuh Dokumentation+1

Wenn Wazuh in Phase 1 program_name: 'CEF' erkennt, ist <program_name>CEF</program_name> als Filter oft zuverlässiger als ein prematch, der „am String-Anfang“ erwartet wird.

2) Regex-Syntax: (\.) matcht einen Punkt – nicht „beliebige Zeichen“

In Wazuh-Decodern ist die Feldextraktion über <regex> + <order> definiert; Regex erfordert dabei zwingend prematch oder program_name (im Decoder selbst oder beim Parent). Wazuh Dokumentation+1

(\.) bedeutet: „matche genau einen Punkt“. Für „bis zum nächsten Pipe“ ist bei CEF-Headern stattdessen sinnvoll:

  • ([^|]*) (alles außer |, auch leer möglich) oder
  • (.+?) (nicht-gierig, wenn man sauber begrenzt)

3) Decoder-Konflikte: „CEF“ ist kein Vendor – Prematch muss die Quelle eindeutig machen

Wenn mehrere Produkte CEF liefern, ist ein Decoder-Parent wie <program_name>CEF</program_name> allein zu breit. Dann „konkurrieren“ CEF-Decodersets. Sauber wird es, wenn der Parent zusätzlich über prematch auf Vendor/Product einschränkt (z. B. |Ubiquiti|UniFi Network| vs. |Incapsula|SIEMintegration|). Das reduziert Überschneidungen drastisch.

4) Extension-Felder: \S+ reicht nicht, wenn Values Leerzeichen enthalten

Im Beispiel ist UNIFIwifiName=Switch-up Workers ein Value mit Leerzeichen. Ein Regex UNIFIwifiName=(\S+) würde nur Switch-up erfassen. Für solche Felder braucht man entweder:

  • ein Pattern, das bis zum nächsten KEY= läuft (Lookahead), oder
  • eine konservative Extraktion über mehrere spezialisierte Kinderdecoder (für Felder ohne Spaces) und separate Behandlung der „problematischen“ Keys.

Für Lookaheads ist es oft sinnvoll, PCRE2 zu nutzen (<regex type="pcre2">). Wazuh unterstützt unterschiedliche Regex-Typen inkl. PCRE2. Stack Overflow+1


Lösung / Best Practices

1) Parent-Decoder: program_name + eindeutiger prematch auf Vendor/Product

Damit UniFi nicht Imperva „in die Quere kommt“, sollte der Parent sowohl program_name als auch Vendor/Product enthalten:

<decoder name="cef-ubiquiti-unifi">
  <program_name>CEF</program_name>
  <prematch>\|\s*Ubiquiti\|\s*UniFi Network\|</prematch>
</decoder>
  • \s* toleriert Whitespace.
  • Der prematch ist bewusst so gewählt, dass er Imperva (Incapsula|SIEMintegration) nicht treffen kann.

2) CEF-Header robust parsen (Version, EventID, Name, Severity)

Der CEF-Header ist klar definiert (CEF:Version|Vendor|Product|Device Version|Signature ID|Name|Severity|…). OpenText+1

Ein robuster Child-Decoder, der Whitespace nach CEF: toleriert und sauber an Pipes trennt:

<decoder name="cef-ubiquiti-unifi-header">
  <parent>cef-ubiquiti-unifi</parent>
  <regex>CEF:\s*0\|Ubiquiti\|UniFi Network\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|</regex>
  <order>ubiquiti.version,ubiquiti.event_id,ubiquiti.name,ubiquiti.severity</order>
</decoder>

Damit vermeidet man die typischen Fehler durch (\.) und stellt sicher, dass der Decoder unabhängig vom Präfix (Timestamp/Hostname) greift.

3) Extension-Felder extrahieren: erst „sichere“ Keys, dann Sonderfälle

Für Felder ohne Leerzeichen ist (\S+) oder IP-Regex okay:

<decoder name="cef-ubiquiti-unifi-kv-category">
  <parent>cef-ubiquiti-unifi</parent>
  <regex>UNIFIcategory=(\S+)</regex>
  <order>unifi.category</order>
</decoder>

<decoder name="cef-ubiquiti-unifi-kv-subcategory">
  <parent>cef-ubiquiti-unifi</parent>
  <regex>UNIFIsubCategory=(\S+)</regex>
  <order>unifi.subcategory</order>
</decoder>

<decoder name="cef-ubiquiti-unifi-kv-clientip">
  <parent>cef-ubiquiti-unifi</parent>
  <regex>UNIFIclientIp=(\d{1,3}(?:\.\d{1,3}){3})</regex>
  <order>srcip</order>
</decoder>

Für Keys mit Leerzeichen im Value (z. B. UNIFIwifiName=Switch-up Workers) empfiehlt sich PCRE2 mit Lookahead „bis zum nächsten KEY=“:

<decoder name="cef-ubiquiti-unifi-kv-wifiname">
  <parent>cef-ubiquiti-unifi</parent>
  <regex type="pcre2">UNIFIwifiName=(.*?)(?=\s+\w+=|$)</regex>
  <order>unifi.wifi_name</order>
</decoder>

Wichtig: Das Lookahead (?=\s+\w+=|$) ist bewusst generisch (nächster Key= oder Zeilenende). PCRE2-Unterstützung ist in Wazuh-Decodern relevant, wenn man solche Konstrukte nutzen möchte. wazuh-documentation-49-master.readthedocs.io+1

4) Konflikte vermeiden: Eindeutige Decoder-Namen und eindeutige Parent-Prematches

Auch wenn Wazuh Decoder-Hierarchien unterstützt, sollte man in Custom-Decodern:

  • eindeutige name-Werte wählen (nicht mehrfach ubiquiti-decoder-child verwenden),
  • pro Produkt/Vendor einen klaren Parent bauen,
  • und nicht auf „CEF allgemein“ matchen, wenn mehrere CEF-Quellen existieren.

5) Testen mit wazuh-logtest und danach Manager neu laden

Wazuh empfiehlt zum Debugging den Einsatz von wazuh-logtest, um Decoding (Phase 1/2) nachvollziehbar zu prüfen. Wazuh Dokumentation+2Wazuh Dokumentation+2
Für produktive Alert-Generierung müssen Decoder-Änderungen anschließend durch Neustart/Reload des Managers wirksam werden (je nach Setup/Workflow). Wazuh Dokumentation


Lessons Learned / Best Practices

  • Program Name nutzen, aber nie allein: <program_name>CEF</program_name> ist stabil, muss aber mit Vendor/Product im prematch kombiniert werden, um Konflikte zu vermeiden. Wazuh Dokumentation+1
  • CEF-Header immer mit [^|]* trennen: Das ist für Pipe-separierte Header deutlich robuster als „irgendwas mit Punkt“. OpenText+1
  • Key-Value-Extension ist trickreich: Values können Leerzeichen enthalten; dafür PCRE2-Lookaheads einsetzen oder Felder selektiv extrahieren. CEF ist explizit als Header + Extension mit Key-Value-Paaren definiert. OpenText+2Delinea Dokumentationsbibliothek+2
  • Regelmäßig mit echten Logs testen: Kleine Formatabweichungen wie CEF: 0| statt CEF:0| sind in der Praxis normal und entscheiden über „matcht“ vs. „matcht nicht“.

Fazit

UniFi-CEF-Decoding in Wazuh scheitert selten an „CEF an sich“, sondern an Details: Whitespace, syslogartige Präfixe, falsche Regex-Platzhalter und zu generische Prematches, die mit anderen CEF-Decodern kollidieren. Mit einem klaren Parent pro Vendor/Product, einem robusten Header-Regex und gezielter Extension-Feldextraktion (inkl. PCRE2 für Values mit Leerzeichen) wird das Decoding stabil, konfliktfrei und langfristig wartbar.

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/p1767608892366969