Kaspersky Security Center CEF in Wazuh sauber dekodieren: Custom Decoder für vollständige Felder statt „nur 3 Werte“

Einleitung

CEF (Common Event Format) ist in vielen SIEM-Pipelines der „kleinste gemeinsame Nenner“ für Security-Telemetrie. In der Praxis stolpern Wazuh-Administratoren aber regelmäßig darüber, dass CEF-Events aus Kaspersky Security Center (KSC) nur teilweise geparst werden: Statt Header + Extension-Key/Value-Paare landen nur wenige Felder im Event. Das ist nicht nur lästig, sondern reduziert direkt den Detection- und Hunting-Mehrwert (z. B. fehlende Host-/User-/Hash-/Pfad-Attribute bei Malware-Funden).

Ausgangslage / Problemstellung

Symptom: Kaspersky-CEF-Logs werden in Wazuh unvollständig dekodiert (z. B. nur wenige Basisfelder), obwohl im Rohlog deutlich mehr Informationen enthalten sind.
Beispielhafte Logstruktur:

  • Präfix mit Timestamp + Quell-IP
  • CEF-Header: CEF:Version|Device Vendor|Device Product|Device Version|Signature ID|Name|Severity|
  • Extension als Key-Value-Paare (msg=... rt=... dhost=... csX=...)

CEF ist formal klar getrennt in Header und Extension, wobei die Extension aus variablen Key-Value-Paaren besteht. OpenText+1
Trotzdem scheitert die Dekodierung in Wazuh oft an (a) zu generischen Prematches, (b) Regex, die „gierig“ matcht oder Sonderzeichen/Newlines in msg= nicht abkann, oder (c) einem Transport, der die Pre-Decoding-Phase (Syslog-Header/Programname) unerwartet beeinflusst. documentation.wazuh.com+1

Technische Analyse

1) Warum „default syslog pattern“ hier nicht reicht

Wazuhs Pre-Decoding extrahiert – sofern ein syslog-ähnlicher Header vorhanden ist – u. a. timestamp, hostname und program_name. Decoder-Filter wie <program_name> funktionieren daher nur zuverlässig, wenn der eingehende Header sauber ist. documentation.wazuh.com+1
In Real-World-Setups kommen Kaspersky-CEF-Events aber teils mit abweichenden Präfixen (oder über Forwarder/Collector, die Felder umstellen). In solchen Fällen matchen Decoder zwar „irgendwie“, aber eben nicht stabil – oder Custom Decoder greifen gar nicht, wenn die Pre-Decoding-Annahmen nicht erfüllt sind. Dieses Muster ist auch in Wazuh-Issues rund um Header-/Predecoder-Probleme dokumentiert. GitHub

2) CEF-Header vs. CEF-Extension: zwei Parsing-Probleme

  • Header ist positionsbasiert (Pipes): Vendor/Product/Version/Signature/Name/Severity. OpenText+1
  • Extension ist key-value-basiert – aber Werte können Leerzeichen enthalten und msg= kann (wie im Malware-Beispiel) Zeilenumbrüche/escaped Newlines tragen. Genau das sprengt naive Regex wie (.*) sehr schnell.

3) Kaspersky-spezifische Stolpersteine

Kaspersky-Produkte exportieren Events in CEF/Syslog gezielt für SIEM-Integrationen; je nach Produktlinie/Komponente unterscheiden sich Felder und Konventionen. Kaspersky beschreibt Aufbau und Eigenschaften von CEF-Syslog-Nachrichten (Header + Body, UTF-8, App-Name etc.). Kaspersky Hilfezentrum+1
Parallel existieren in der Wazuh-Ruleset-Welt bereits Kaspersky-bezogene Decoder, aber nicht zwingend für KSC-CEF in der hier gezeigten Form (z. B. gibt es Regeln/Decoder für andere Kaspersky-Quellen oder andere Strukturierungen). GitHub

Lösung / Best Practices

Unten ist ein praxistauglicher Ansatz, der den im Rohmaterial gezeigten Decoder-Gedanken professionalisiert: stabiler Parent-Decoder + getrennte Child-Decoder, um Header, msg= und Extension-Felder robust zu extrahieren. Grundlage ist Wazuhs Decoder-Syntax (Parent/Child, <prematch>, <regex>, offset="after_regex"). documentation.wazuh.com+1

1) Custom Decoder-Datei sauber anlegen

Lege die Decoder in einer lokalen Datei ab, z. B.:
/var/ossec/etc/decoders/local_decoder.xml
und beachte die Wazuh-Empfehlungen für Custom Decoder (update-sicher arbeiten, Originaldateien nicht „überschreiben“). documentation.wazuh.com

2) Robuster Decoder für KSC-CEF (Header + Extension)

Wichtiges Design-Ziel: Prematch eng genug, damit nicht jeder CEF-Producer darunter fällt, aber tolerant genug für Prefix-Variationen.

<!-- Parent: identifiziert Kaspersky Security Center CEF zuverlässig -->
<decoder name="ksc_cef_parent">
  <!-- Viele Setups haben im Event "CEF:" direkt im Payload; daher prematch auf Vendor/Product -->
  <prematch>CEF:\s*\d+\|KasperskyLab\|SecurityCenter\|</prematch>
</decoder>

<!-- Child: CEF-Header (positionsbasiert) -->
<decoder name="ksc_cef_header">
  <parent>ksc_cef_parent</parent>
  <!-- Header endet nach Severity und dem folgenden "|" -->
  <regex>CEF:\s*(\d+)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|(\d+)\|</regex>
  <order>cef.version,cef.deviceVendor,cef.deviceProduct,cef.deviceVersion,cef.signatureID,cef.name,cef.severity</order>
</decoder>

<!-- Child: msg=... (kann Leerzeichen und escaped Newlines enthalten) -->
<decoder name="ksc_cef_msg">
  <parent>ksc_cef_parent</parent>
  <!-- Offset nach dem Header-Regex: wir gehen "nach dem Header" weiter -->
  <regex offset="after_regex">msg=(.*?)\s+rt=</regex>
  <order>cef.msg</order>
</decoder>

<!-- Child: Core Extension-Felder (stabil, häufig vorhanden) -->
<decoder name="ksc_cef_ext_core">
  <parent>ksc_cef_parent</parent>
  <regex>rt=(\d+)\s+cs9=(.*?)\s+cs9Label=(\S+)\s+dhost=(\S+)\s+dst=(\S+)\s+cs2=(\S+)\s+cs2Label=(\S+)\s+cs3=(\S+)\s+cs3Label=(\S+)</regex>
  <order>cef.rt,ksc.group,ksc.groupLabel,host.name,dst.ip,ksc.productName,ksc.productNameLabel,ksc.productVersion,ksc.productVersionLabel</order>
</decoder>

<!-- Child: Threat-/Task-spezifische Felder (optional, nur wenn vorhanden) -->
<decoder name="ksc_cef_ext_threat">
  <parent>ksc_cef_parent</parent>
  <regex>cs10=(.*?)\s+cs10Label=(\S+)\s+cs4=(\S+)\s+cs4Label=(\S+)\s+filePath=(.*?)\s+cs1=(\S+)\s+cs1Label=(\S+)\s+duser=(\S+)\s+cs6=(.*?)\s+cs6Label=(\S+)\s+engine=(\d+)\s+method=(\d+)</regex>
  <order>ksc.task,ksc.taskLabel,file.hash.sha256,ksc.sha256Label,file.path,threat.name,ksc.threatLabel,user.name,ksc.extraAttrib,ksc.extraAttribLabel,ksc.engine,ksc.method</order>
</decoder>

Was wurde gegenüber „naivem“ Regex verbessert?

  • Statt (\.*) wird gezielt bis zum nächsten Feld bzw. mit nicht-gierigen Gruppen gearbeitet ((.*?)), um nicht „alles zu schlucken“.
  • Der Header wird exakt als CEF-Header geparst (Pipes, feste Feldanzahl) gemäß CEF-Standard. OpenText+1
  • Die Decoder sind modular: Wenn ein Event keine Threat-Felder hat, greift trotzdem ksc_cef_ext_core.

3) Regex testen, bevor du den Manager neu startest

Nutze wazuh-regex, um Regex gegen Beispielzeilen zu testen, bevor du in den Live-Pfad gehst. documentation.wazuh.com
Das spart Neustarts und verhindert „silent failures“, bei denen Decoder einfach nicht matchen.

4) Transport/Zeilenumbrüche in msg= entschärfen

Wenn msg= echte Zeilenumbrüche enthält (nicht nur \r\n als Text), kann ein Syslog-Forwarder daraus mehrere Zeilen machen – Wazuh sieht dann getrennte Events. Best Practice ist, im Forwarder sicherzustellen, dass pro CEF-Event genau eine Zeile ankommt (oder Multiline-Handling gezielt zu konfigurieren). Probleme rund um nicht-standardkonforme Header/Predecoding sind ein bekannter Fallstrick in Wazuh, daher Transport/Normalisierung früh in der Pipeline klären. GitHub+1

5) Kaspersky-Export korrekt konfigurieren

Je nach KSC-Version/Lizenz und Exportmodus (CEF/LEEF/Syslog) unterscheidet sich, was überhaupt exportiert wird. Kaspersky dokumentiert die SIEM-Export-Konfiguration für KSC inklusive CEF/LEEF-Optionen. Kaspersky Hilfezentrum+1
Wenn Events „zu dünn“ erscheinen, ist das nicht immer ein Decoder-Problem – manchmal exportiert KSC nur eine Teilmenge (z. B. „general events“). Kaspersky Hilfezentrum

Lessons Learned / Best Practices

  • Prematch präzise halten: CEF: ...|KasperskyLab|SecurityCenter| ist stabiler als generisches program_name=CEF, weil der Syslog-Header in der Praxis variieren kann. documentation.wazuh.com+1
  • Header und Extension getrennt parsen: CEF ist semantisch zweigeteilt; modularisierte Decoder sind wartbarer und fehlertoleranter. OpenText+1
  • Nicht-gierige Matches in Extension: Vor allem msg= ist eine „Falle“ (Spaces, \r\n, lange Texte).
  • Pre-Decoding nicht als gegeben annehmen: Wenn Forwarder/Collector den Syslog-Prefix verändern, können <program_name>-basierte Filter unzuverlässig werden. Das zeigt sich auch in aktuellen Wazuh-Diskussionen/Issues zu Header-Konformität. GitHub
  • Vorhandene Ruleset-Artefakte prüfen: Es existieren Kaspersky-nahe Decoder im Wazuh-Ökosystem, aber sie passen nicht automatisch zu jedem KSC-CEF-Flavor – daher bewusst abgleichen und ggf. ergänzen. GitHub

Fazit

Kaspersky Security Center liefert in CEF deutlich mehr als „ein paar Felder“ – aber nur, wenn Wazuh den CEF-Header sauber trennt, die Extension robust per Child-Decodern extrahiert und msg= nicht das Parsing sprengt. Mit einem präzisen Prematch, modularen Decodern und einem sauberen Transport (eine Message = eine Zeile) bekommst du reproduzierbar vollständige Attribute für Detection, Korrelation und Incident Response.

Mehr zu Wazuh …

Mehr zum Wazuh Ambassador Program …

https://wazuh.slack.com/archives/C0A933R8E/p1766125832329589