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 generischesprogram_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 zum Wazuh Ambassador Program …
https://wazuh.slack.com/archives/C0A933R8E/p1766125832329589