Einleitung
Die Überwachung von USB-Geräten ist in Wazuh ein typischer Anwendungsfall für Endpoint Visibility, Datenabflussprävention und die Erkennung unerlaubter Peripherie. Gerade in Windows-Umgebungen wird häufig versucht, autorisierte Datenträger über CDB-Listen zu erlauben und unbekannte Geräte als verdächtig zu markieren. In der Praxis scheitert diese Logik jedoch oft nicht an Wazuh selbst, sondern an einer falschen Annahme darüber, wie CDB-Listen Felder vergleichen und wie Parent-/Child-Regeln zusammenspielen. Die offizielle Wazuh-Dokumentation beschreibt CDB-Listen als exakte Key-Lookups, und der offizielle USB-Monitoring-Ansatz für Windows trennt explizit zwischen generischer USB-Erkennung und einer negativen Listenprüfung für nicht autorisierte Geräte.
Ausgangslage / Problemstellung
Ausgangspunkt war eine benutzerdefinierte Windows-Regel, die auf Event ID 6416 und den String USBSTOR\\Disk prüft. Darauf aufbauend sollte eine nachgelagerte Regel mit einer CDB-Liste autorisierte USB-Geräte erkennen. Das beobachtete Verhalten war jedoch widersprüchlich: Die Basisregel für das eingesteckte Gerät löste aus, die vermeintliche Autorisierungsregel dagegen nicht. Parallel dazu existierte ein Linux-Ansatz, bei dem auf das Feld serial geprüft wird. Zusätzlich entstand Verwirrung, weil ein Test mit lookup="not_match_key" scheinbar „Authorized“-Treffer erzeugte, obwohl dies laut Dokumentation eigentlich das Gegenteil bedeutet.
Typisch für diese Situation ist, dass in der CDB-Liste nur ein Teilwert des Gerätebezeichners hinterlegt wird, etwa nur die Seriennummer oder der letzte Abschnitt der deviceId. Bei Windows enthält das Feld win.eventdata.deviceId jedoch den vollständigen Wert, beispielsweise inklusive Präfixen wie USBSTOR\\Disk&Ven_.... Eine CDB-Liste arbeitet hier nicht wie <match> oder <regex>, sondern vergleicht den kompletten Schlüssel gegen den kompletten Feldinhalt. Schon ein fehlender Präfix, ein abweichendes Escape-Verhalten oder ein zusätzliches Leerzeichen verhindert den Treffer.
Technische Analyse
Der Kern des Problems liegt in der Semantik von <list> innerhalb einer Wazuh-Regel. lookup="match_key" bedeutet einen positiven Treffer: Die Regel matcht nur dann, wenn der Inhalt des angegebenen Feldes exakt als Schlüssel in der CDB-Liste vorhanden ist. lookup="not_match_key" ist dagegen ein negativer Treffer und matcht nur dann, wenn der Feldwert nicht in der CDB-Liste enthalten ist. Das ist in der Dokumentation eindeutig definiert.
Für Windows-USB-Monitoring ist außerdem entscheidend, wie die Regelkette aufgebaut wird. Der offizielle Wazuh-Blog verwendet zunächst eine generische Regel, die jeden relevanten USB-Anschluss erkennt. Danach folgt eine Regel für autorisierte Geräte ohne Listenprüfung als unmittelbares Child der Basisregel, und eine zweite Regel für nicht autorisierte Geräte mit lookup="not_match_key". Dadurch ist die Logik eindeutig: Zuerst wird das Ereignis erkannt, danach wird nur für die unerlaubten Geräte ein zusätzlicher Treffer erzeugt, wenn die deviceId nicht in der Liste vorhanden ist.
Genau hier lag die Verwirrung im diskutierten Regelset. Die Regel
<rule id="199001" level="5">
<if_sid>199000</if_sid>
<list field="win.eventdata.deviceId" lookup="not_match_key">etc/lists/windows-usb-drives</list>
<description>Windows: Authorized PNP device ...</description>
</rule>
ist semantisch widersprüchlich. Technisch würde sie nur matchen, wenn das Gerät nicht in der Liste steht. Die Beschreibung „Authorized“ ist also falsch. Dass damit „positive Ergebnisse“ sichtbar wurden, ist kein Beweis gegen die Dokumentation, sondern ein Hinweis darauf, dass die Regelbeschriftung und die Lookup-Logik nicht zusammenpassen. Die Regel arbeitet dann als „Unauthorized“, auch wenn der Beschreibungstext etwas anderes behauptet.
Hinzu kommt ein zweiter Stolperstein: CDB-Listen müssen im <ruleset>-Block der ossec.conf referenziert werden, und Änderungen werden erst nach einem Neustart des Wazuh Managers wirksam, weil die CDB-Dateien beim Start gebaut und geladen werden. Wenn nur die XML-Regel angepasst wurde, die Liste aber nicht im Ruleset registriert oder der Manager nicht neu gestartet wurde, bleibt die Listenprüfung wirkungslos. Auch dieser Punkt ist in der Wazuh-Dokumentation explizit beschrieben.
Ein dritter technischer Punkt betrifft die Wahl des Operators. <match> und <regex> sind für Mustererkennung gedacht, also etwa für Teilstrings oder variable Formate. CDB-Listen sind dagegen für deterministische Allow-/Deny-Listen geeignet. Bei langen Listen ist CDB meist die richtige Wahl, aber nur dann, wenn das zu prüfende Feld stabil und vollständig vorliegt. Bei Windows-USB-Geräten sollte daher die komplette win.eventdata.deviceId in die Liste übernommen werden, nicht nur der serielle Suffix.
Lösung / Best Practices
Für Windows sollte die Logik in drei Ebenen aufgebaut werden: eine Basiserkennung, eine Regel für autorisierte Geräte und eine separate Regel für nicht autorisierte Geräte. Die Basiserkennung identifiziert das relevante Event, die Autorisierungsentscheidung erfolgt danach über die CDB-Liste.
Ein belastbarer Aufbau orientiert sich an der offiziellen Wazuh-Logik:
<group name="windows-usb-detect,">
<rule id="199000" level="8">
<if_sid>60103</if_sid>
<field name="win.system.eventID">^6416$</field>
<match>USBSTOR\\Disk</match>
<options>no_full_log</options>
<description>Windows: PNP device $(win.eventdata.deviceDescription) was connected to $(win.system.computer)</description>
</rule> <rule id="199001" level="5">
<if_sid>199000</if_sid>
<list field="win.eventdata.deviceId" lookup="match_key">etc/lists/windows-usb-drives</list>
<options>no_full_log</options>
<description>Windows: Authorized PNP device $(win.eventdata.deviceDescription) was connected to $(win.system.computer)</description>
</rule> <rule id="199002" level="8">
<if_sid>199000</if_sid>
<list field="win.eventdata.deviceId" lookup="not_match_key">etc/lists/windows-usb-drives</list>
<options>no_full_log</options>
<description>Windows: Unauthorized PNP device $(win.eventdata.deviceDescription) was connected to $(win.system.computer)</description>
</rule>
</group>
Damit ist die Semantik sauber getrennt: 199001 trifft nur bei exakter Übereinstimmung in der Allowlist, 199002 nur bei fehlendem Eintrag. Diese Struktur entspricht auch dem Prinzip aus dem offiziellen Windows-USB-Beispiel von Wazuh, bei dem die Erkennung autorisierter und nicht autorisierter Geräte getrennt modelliert wird.
Ebenso wichtig ist der Inhalt der CDB-Datei. Für Windows muss dort der exakte Inhalt von win.eventdata.deviceId stehen, beispielsweise:
USBSTOR\\Disk&Ven__USB&Prod__SanDisk_3.2Gen1&Rev_1.00\\090185804650135a31cc2164259fda883b585bc34588db7fafbb71aec2fccff
Wird stattdessen nur
090185804650135a31cc2164259fda883b585bc34588db7fafbb71aec2fccff
eingetragen, kann match_key nicht funktionieren, weil keine exakte Schlüsselgleichheit vorliegt. Genau das ist der häufigste Grund dafür, dass die „erste Regel“ triggert, die Listenregel aber nicht.
Die Listen selbst sollten unter /var/ossec/etc/lists/ liegen, im <ruleset>-Block referenziert werden und nach jeder Änderung einen Neustart des Managers auslösen:
<ruleset>
<decoder_dir>ruleset/decoders</decoder_dir>
<rule_dir>ruleset/rules</rule_dir>
<rule_exclude>0215-policy_rules.xml</rule_exclude>
<list>etc/lists/audit-keys</list>
<list>etc/lists/amazon/aws-eventnames</list>
<list>etc/lists/security-eventchannel</list> <decoder_dir>etc/decoders</decoder_dir>
<rule_dir>etc/rules</rule_dir>
<list>etc/lists/linux-usb-drives</list>
<list>etc/lists/windows-usb-drives</list>
</ruleset>
systemctl restart wazuh-manager
Ohne diese Referenzierung oder ohne Neustart wird die CDB-Liste nicht korrekt geladen.
Für Linux ist das Prinzip ähnlich, allerdings ist dort das Feldmodell ein anderes. Wenn das Feld serial dekodiert wird und genau dieser Wert in der Liste steht, ist lookup="match_key" für autorisierte Geräte korrekt:
<group name="linux,usb,">
<rule id="111010" level="7">
<field name="serial">\w+</field>
<field name="type">usb_device</field>
<description>A PNP device $(vendor) $(model) was connected to $(hostname).</description>
</rule> <rule id="111011" level="5">
<if_sid>111010</if_sid>
<list field="serial" lookup="match_key">etc/lists/linux-usb-drives</list>
<description>Authorized PNP device $(vendor) $(model) was connected to $(hostname).</description>
</rule> <rule id="111012" level="8">
<if_sid>111010</if_sid>
<list field="serial" lookup="not_match_key">etc/lists/linux-usb-drives</list>
<description>Unauthorized PNP device $(vendor) $(model) was connected to $(hostname).</description>
</rule>
</group>
Der Unterschied zwischen Linux und Windows ist hier also nicht die Bedeutung von match_key, sondern die Struktur des dekodierten Feldes. Unter Linux kann serial bereits der relevante eindeutige Identifier sein; unter Windows ist win.eventdata.deviceId meist ein längerer, zusammengesetzter Wert.
Lessons Learned / Best Practices
Die wichtigste Erkenntnis ist, dass CDB-Listen in Wazuh keine Teilstring-Suche durchführen. Wer USB-Geräte über Allowlists steuern möchte, muss immer mit dem vollständigen dekodierten Feldwert arbeiten. Das gilt insbesondere für Windows-Events, deren deviceId Hersteller-, Produkt- und Revisionsinformationen mit dem eigentlichen Gerätebezeichner kombiniert.
Ebenso wichtig ist eine saubere Trennung zwischen Erkennung und Klassifizierung. Eine Parent-Regel sollte das Event identifizieren, Child-Regeln sollten es anschließend als autorisiert oder nicht autorisiert klassifizieren. Werden Beschreibungstexte und Lookup-Operatoren vertauscht, entstehen zwar Alerts, aber ihre Bedeutung ist fachlich falsch. Im Security-Betrieb ist das riskant, weil Dashboards, Korrelationen und Incident-Workflows dann auf einer fehlerhaften Semantik aufbauen.
Für produktive Umgebungen empfiehlt es sich außerdem, neue Regeln immer mit realen Eventdaten zu validieren. Entscheidend ist nicht, wie der Identifier „aussieht“, sondern wie er nach dem Decoding tatsächlich im Feld ankommt. Ein Copy-and-Paste des exakten Feldinhalts aus dem Event ist zuverlässiger als eine manuell rekonstruierte Zeichenkette. Zusätzliche Leerzeichen, HTML-escapte Zeichen oder falsch übernommene Backslashes reichen bereits aus, um einen CDB-Treffer zu verhindern. Diese Anfälligkeit ergibt sich unmittelbar aus der dokumentierten Exact-Match-Logik der CDB-Listen.
Fazit
Das beobachtete Verhalten war kein Widerspruch zur Wazuh-Dokumentation, sondern das Ergebnis zweier klassischer Fehlerquellen: erstens einer nicht exakt passenden win.eventdata.deviceId in der CDB-Liste und zweitens einer vertauschten Regel-Logik, bei der not_match_key fälschlich als „Authorized“ beschriftet wurde. Die saubere Lösung besteht darin, die Basisregel von der Klassifizierung zu trennen, für autorisierte Geräte match_key mit dem vollständigen Feldwert zu verwenden und für nicht autorisierte Geräte eine separate Regel mit not_match_key einzusetzen. So wird aus einer scheinbar inkonsistenten USB-Erkennung ein belastbares, nachvollziehbares Wazuh-Regelset für den produktiven Security-Betrieb.
Quellenverweis
Wazuh Dokumentation – Using CDB lists
https://documentation.wazuh.com/current/user-manual/ruleset/cdb-list.html
Wazuh Dokumentation – Rules Syntax
https://documentation.wazuh.com/current/user-manual/ruleset/ruleset-xml-syntax/rules.html
Wazuh Dokumentation – ruleset in ossec.conf
https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/ruleset.html
Wazuh Blog – Monitoring USB drives in Windows using Wazuh
https://wazuh.com/blog/monitoring-usb-drives-in-windows-using-wazuh/
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/p1771482513626369