Forcepoint DLP CEF in Wazuh zuverlässig dekodieren: Warum „cat=…:“ Single-Regex bricht – und wie Sibling-Decoder es sauber lösen

Einleitung

Forcepoint DLP liefert für SIEM-Integrationen häufig CEF über Syslog. Auf dem Papier ist das ideal: ein standardisierter CEF-Header plus Extension als Key-Value-Paare. In der Praxis scheitert die Dekodierung in Wazuh aber oft genau dort, wo DLP-Events wertvoll werden: bei freien Textfeldern und Policy-/Kategorie-Namen mit Leerzeichen, Sonderzeichen oder Doppelpunkten. Das führt zu unvollständigen Feldern und damit zu schwächerer Korrelation (User ↔ URL ↔ Policy ↔ Source IP) und schlechterer Alarmqualität.

Ausgangslage / Problemstellung

Ein typisches Forcepoint-DLP-Event sieht so aus (gekürzt):
… CEF:0|Forcepoint|Forcepoint DLP|10.3.0|9376294|DLP Syslog|1| act=Permitted duser=… msg=https://… suser=… cat=DLP Developers Policy: yy sourceServiceName=HTTPS analyzedBy=… loginName=… sourceIp=… severityType=… destinationHosts=… eventId=…

Symptom:

  • Mit sehr generischen Decodern werden nur wenige Felder extrahiert.
  • Ein „Single-Line“-Decoder, der viele Felder in einer Regex abgreift, funktioniert bis cat=…, bricht aber, sobald cat= einen Doppelpunkt enthält oder der Wert nicht sauber durch „nächstes Feld“ begrenzt ist.

Das ist kein Forcepoint-Sonderfall, sondern ein klassischer CEF-Parsing-Fall: CEF besteht aus Syslog-Prefix, CEF-Header und CEF-Extension; die Extension ist variabel und enthält Key-Value-Paare. OpenText+1

Technische Analyse

1) Warum man „vor CEF“ meist bewusst ignoriert

Der Teil vor CEF: ist Transport-/Prefix-Schicht (Timestamp, Relay/Hostname, ggf. RFC3164/5424). Er kann je nach Forwarder, Syslog-Daemon, NAT oder Log-Relay variieren – CEF beginnt zuverlässig erst bei CEF:. Deshalb ist ein Prematch auf konstante CEF-Header-Komponenten (Vendor/Product) oft stabiler als ein Match auf den wechselnden Prefix. NXLog+1

2) Warum der Single-Regex-Ansatz an cat= scheitert

Im Beispiel ist cat=DLP Developers Policy: yy problematisch aus zwei Gründen:

  • Leerzeichen + Doppelpunkt im Wert: cat= ist nicht „ein Wort“, sondern ein freier Text.
  • Begrenzung fehlt: Wenn die Regex cat=(.+) verwendet, ist sie gierig und zieht typischerweise bis zum Ende der Zeile (oder bis sie später zufällig wieder „passen“ kann). Der nächste Key sourceServiceName= kommt nicht mehr sauber zum Zug.

Wazuhs Decoder-Regex (OS_Regex) ist schnell, aber nicht „magisch“: Ohne eindeutige Trennmarker und ohne nicht-gierige/bounded Patterns wird ein Feld wie cat= zur „Staubsauger-Gruppe“. Wazuh dokumentiert das Regex-Verhalten und die verfügbaren Regex-Typen explizit. documentation.wazuh.com+1

3) Warum Sibling-Decoder hier die bestmögliche Betriebsstrategie sind

Sibling-Decoder sind in Wazuh genau für dynamische Logs gedacht: viele kleine Decoder statt „eine riesige Regex“. Vorteil: Wenn ein Feld mal anders formatiert ist, fallen nicht automatisch alle nachfolgenden Felder aus. documentation.wazuh.com+1
Das ist bei DLP-Logs entscheidend, weil Policy-Namen, Kategorien, URLs und User-Strings je nach Use Case extrem variieren.

4) Forcepoint-spezifischer Kontext: Syslog/CEF ist konfigurativ

Forcepoint DLP kann Syslog-Ausgaben konfigurativ steuern (Syslog-Server/Port, „Send syslog message“ etc.). Dadurch unterscheiden sich Umgebungen teils in Prefix, Event-Typen und Feldumfang. help.forcepoint.com+1
Zusätzlich sieht man in Drittanbieter-Parsers (z. B. Chronicle/Google Security Operations), dass Forcepoint-DLP-CEF typischerweise als Key-Value-Parsing behandelt wird, nicht als „fixed order“-Log. Google Cloud+1

Lösung / Best Practices

Ziel: Stabiler Parent-Decoder, dann CEF-Header getrennt vom Extension-Key/Value-Parsing, und für cat= ein bounded Match bis zum nächsten Key (sourceServiceName=).

Ablageort: Custom Decoder gehören in eine lokale Datei wie /var/ossec/etc/decoders/local_decoder.xml (oder eine eigene Custom-Datei), gemäß Wazuh Decoder-Syntax. documentation.wazuh.com+1

1) Parent + CEF-Header korrekt dekodieren

<decoder name="forcepoint_dlp_cef_parent">
  <prematch>CEF:0\|Forcepoint\|Forcepoint DLP\|</prematch>
</decoder>

<decoder name="forcepoint_dlp_cef_header">
  <parent>forcepoint_dlp_cef_parent</parent>
  <regex>CEF:(\d+)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|(\d+)\|</regex>
  <order>cef.version,cef.deviceVendor,cef.deviceProduct,cef.deviceVersion,cef.signatureID,cef.name,cef.severity</order>
</decoder>

Warum so? CEF ist formal Header + Extension; der Header ist positionsbasiert und endet nach Severity + Pipe. OpenText+1

2) Extension-Felder als Sibling-Decoder (robust, wartbar)

<decoder name="forcepoint_dlp_act">
  <parent>forcepoint_dlp_cef_parent</parent>
  <regex>\sact=([^\s]+)</regex>
  <order>action</order>
</decoder>

<decoder name="forcepoint_dlp_duser">
  <parent>forcepoint_dlp_cef_parent</parent>
  <regex>\sduser=([^\s]+)</regex>
  <order>dstuser</order>
</decoder>

<decoder name="forcepoint_dlp_msg">
  <parent>forcepoint_dlp_cef_parent</parent>
  <regex>\smsg=([^\s]+)</regex>
  <order>url</order>
</decoder>

<decoder name="forcepoint_dlp_suser">
  <parent>forcepoint_dlp_cef_parent</parent>
  <regex>\ssuser=([^\s]+)</regex>
  <order>srcuser</order>
</decoder>

<!-- Wichtig: cat bis zum nächsten Key begrenzen -->
<decoder name="forcepoint_dlp_cat">
  <parent>forcepoint_dlp_cef_parent</parent>
  <regex>\scat=(.*?)\ssourceServiceName=</regex>
  <order>category</order>
</decoder>

<decoder name="forcepoint_dlp_sourceServiceName">
  <parent>forcepoint_dlp_cef_parent</parent>
  <regex>\ssourceServiceName=([^\s]+)</regex>
  <order>service</order>
</decoder>

<decoder name="forcepoint_dlp_analyzedBy">
  <parent>forcepoint_dlp_cef_parent</parent>
  <regex>\sanalyzedBy=(.*?)\sloginName=</regex>
  <order>analyzed_by</order>
</decoder>

<decoder name="forcepoint_dlp_loginName">
  <parent>forcepoint_dlp_cef_parent</parent>
  <regex>\sloginName=([^\s]+)</regex>
  <order>user.upn</order>
</decoder>

<decoder name="forcepoint_dlp_sourceIp">
  <parent>forcepoint_dlp_cef_parent</parent>
  <regex>\ssourceIp=([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)</regex>
  <order>srcip</order>
</decoder>

<decoder name="forcepoint_dlp_severityType">
  <parent>forcepoint_dlp_cef_parent</parent>
  <regex>\sseverityType=([^\s]+)</regex>
  <order>severity_type</order>
</decoder>

<decoder name="forcepoint_dlp_destinationHosts">
  <parent>forcepoint_dlp_cef_parent</parent>
  <regex>\sdestinationHosts=([^\s]+)</regex>
  <order>dsthost</order>
</decoder>

<decoder name="forcepoint_dlp_eventId">
  <parent>forcepoint_dlp_cef_parent</parent>
  <regex>\seventId=([0-9]+)</regex>
  <order>event_id</order>
</decoder>

Warum funktioniert das zuverlässig?

  • cat= wird nicht mit (.+) „bis zum Ende“ gematcht, sondern bis zum nächsten Key (sourceServiceName=). Damit sind Doppelpunkt und Leerzeichen im Category-Wert egal.
  • Felder wie analyzedBy= werden ebenfalls bounded (bis loginName=), weil sie ebenfalls Leerzeichen enthalten können.
  • Bei Abweichungen (z. B. fehlendes Feld) werden die anderen Felder trotzdem dekodiert – Kernvorteil von Sibling-Decodern. documentation.wazuh.com+1

3) Teststrategie

  • Nutze wazuh-logtest, um Decoder-Matches iterativ zu prüfen, bevor du produktiv reloadest.
  • Wenn du „Single Regex“ trotzdem bevorzugst: dann nur mit konsequenten Boundaries (… cat=(.*?) sourceServiceName=…) und nicht mit gierigen Platzhaltern. Wazuhs Regex-Dokumentation ist hier die Referenz für erlaubte Syntax/Quantifier. documentation.wazuh.com+1

Lessons Learned / Best Practices

  • CEF immer in Schichten denken: Syslog-Prefix (variabel) → CEF-Header (Pipes) → Extension (Key-Value). NXLog+1
  • Prematch auf konstante Vendor/Product-Teile: CEF:0|Forcepoint|Forcepoint DLP| ist stabil, Prefix davor nicht.
  • Keine gierigen Catch-Alls in der Extension: Freitext-Felder (cat/analyzedBy/Policy-Namen) immer bis zum nächsten Key begrenzen.
  • Sibling-Decoder sind bei DLP/CEF die Default-Wahl: weniger fragil, besser wartbar, toleranter gegenüber Feldvarianten. documentation.wazuh.com+1
  • Quelle/Exporter verstehen: Forcepoint Syslog/CEF-Ausgabe ist konfigurationsabhängig; Änderungen an Remediation/Syslog-Settings oder Event-Typen beeinflussen Prefix/Feldumfang. help.forcepoint.com+1

Fazit

Der Decoder bricht nicht „wegen des Doppelpunkts“, sondern wegen eines typischen Parsing-Fehlers: ungebundene, gierige Regex-Gruppen auf CEF-Extension-Feldern mit Freitext. Die robuste Lösung ist, CEF-Header sauber separat zu dekodieren und die Extension mit Sibling-Decodern sowie klaren Feldgrenzen zu parsen – insbesondere bei cat= und ähnlichen Feldern. Das liefert in Wazuh reproduzierbar vollständige Felder für Korrelation, Alarmierung und Incident Response.

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