Im Thread wollte Logitech Flames folgendes erreichen:
- Zeek extrahiert Dateien nach:
/var/lib/zeek/completed - Wazuh erkennt neue Dateien dort und löst Rule 100100 aus:
<group name="zeek,syscheck,"> <rule id="100100" level="7"> <if_sid>554</if_sid> <field name="file">^/var/lib/zeek/completed</field> <description>New file detected in Zeek completed folder: $(file)</description> <mitre> <id>T1005</id> </mitre> <group>zeek_file_monitoring,</group> </rule> </group> - Diese Rule triggert eine MISP-Integration:
<integration> <name>custom-misp_file_hashes.py</name> <hook_url>https://192.168.18.30:9443</hook_url> <api_key>…</api_key> <rule_id>554,100100</rule_id> <alert_format>json</alert_format> <options>{ "timeout": 10, "retries": 3, "debug": true, "push_sightings": true, "sightings_source": "wazuh" } </options> </integration> - Zusätzlich gibt es eine MISP-Resultat-Rule:
<group name="misp,malware,"> <rule id="100800" level="0"> <decoded_as>json</decoded_as> <description>MISP: file hash check</description> <field name="integration">misp_file_hashes</field> <options>no_full_log</options> </rule> </group>
Ergebnis:
- Rule 100100 („New file detected…“) triggert → sieht keine MISP-Daten
- Rule 100800 triggert später → enthält alle MISP-Infos zum Hash
Die Frage war:
„Wie bekomme ich die MISP-Metadaten in denselben Alert wie Rule 100100?“
1. Wichtiger Grundsatz: Wazuh-Alerts sind „fertig“, sobald sie geschrieben sind
[Wazuh] Hossam bringt den Knackpunkt ziemlich klar auf den Punkt:
Wazuh-Alerts sind praktisch unveränderlich.
Wenn ein Alert einmal ausgelöst und indiziert ist, wird er nicht nachträglich angereichert.
Dabei spielen zwei Dinge zusammen:
- Rule 100100 löst aus, Wazuh schreibt den Alert in den Index → fertig.
- Danach wird dein Python-Script (
custom-misp_file_hashes.py) aufgerufen:- es fragt die MISP-API ab
- findet evtl. einen Match
- produziert einen neuen Event/Alert (z. B. Rule 100800)
Das heißt:
- Der ursprüngliche Alert (100100) kann die MISP-Daten gar nicht haben,
weil die MISP-Abfrage erst danach stattfindet. - Eine „Rückschreibung“ in den alten Alert sieht Wazuh nicht vor.
2. Korrekte Denke: Der zweite Alert wird dein „Hauptalarm“
Statt zu versuchen, den ersten Alert anzureichern, solltest du:
- den von der MISP-Integration erzeugten Alert (z. B. Rule 100800)
- zu deinem primären, voll angereicherten Alarm machen
Das heißt konkret:
- Der erste Alert („neue Datei entdeckt“) ist eher ein technischer Trigger.
- Der zweite Alert („MISP-Hash matched“) soll enthalten:
- Hash
- MISP-Daten (Threat-Level, Tags, Event-ID, Attribute…)
- und lokale Kontextdaten (z. B. Dateipfad / Host / Zeek-Info)
Damit hast du einen Alert, den dein SOC/Team wirklich braucht – und kannst den reinen FIM-Trigger ignorieren oder herunterstufen.
3. Wie du das erreichst: Python-Skript als „Daten-Brücke“ nutzen
Die Lösung ist nicht in Wazuh XML, sondern in deiner Integrationslogik:
Du musst dein
custom-misp_file_hashes.pyso umbauen,
dass es Kontext aus dem Eingangsalert übernimmt
und in den Antwort-Event wieder einbaut.
Schritt 1 – Eingangsdaten aus Wazuh lesen
Wazuh übergibt dem Integration-Skript den Alert (z. B. über STDIN oder eine Datei, je nach Template).
Typisch liest man das so:
import json
import sys
alert = json.load(sys.stdin)
file_path = alert.get("data", {}).get("syscheck", {}).get("path") \
or alert.get("file") # je nach Struktur
sha256 = alert.get("data", {}).get("syscheck", {}).get("sha256")
agent_name = alert.get("agent", {}).get("name")
In deinem Zeek-Case kommt der Pfad vermutlich anders, aber das Prinzip bleibt:
- Dateipfad / Hash / Agent aus dem ursprünglichen Alert herausziehen
- alles, was du später im MISP-Alert wieder sehen willst, hier bereits speichern
Schritt 2 – MISP abfragen (wie bisher)
Das machst du vermutlich ohnehin schon:
from pymisp import ExpandedPyMISP
misp = ExpandedPyMISP(MISP_URL, MISP_API_KEY, ssl=False)
result = misp.search("attributes", value=sha256)
Dabei bekommst du Event/Attribute-Infos, die du im Output-JSON verwenden kannst.
Schritt 3 – Kontext in den Output einbauen
Statt nur die MISP-Infos zu senden, baust du beides in die Antwort ein:
output = {
"integration": "misp_file_hashes",
"file": file_path,
"agent": agent_name,
"hash": sha256,
"misp": {
"matched": True,
"events": [
{
"id": ev["Event"]["id"],
"info": ev["Event"]["info"],
"threat_level_id": ev["Event"]["threat_level_id"],
"tags": [t["name"] for t in ev["Event"].get("Tag", [])]
}
for ev in result
]
}
}
print(json.dumps(output))
Dadurch entsteht ein neuer Event, den Wazuh wieder einliest und der dann von deiner Rule 100800 gepflückt wird.
4. Rule 100800 so bauen, dass sie den Kontext nutzt
Jetzt kannst du in der MISP-Rule nicht nur erkennen, dass die Integration gelaufen ist, sondern auch:
- welchen Pfad
- welchen Agent
- welches Hash
- welche MISP-Bewertung
z. B.:
<group name="misp,malware,">
<rule id="100800" level="12">
<decoded_as>json</decoded_as>
<field name="integration">^misp_file_hashes$</field>
<field name="misp.matched">^true$</field>
<description>
MISP match for file $(file) on agent $(agent) – hash: $(hash)
</description>
<group>misp_alert,threat_intel,</group>
</rule>
</group>
Damit bekommst du am Ende genau das, was du willst:
- ein Alert, der:
- den Dateipfad enthält
- den Host (Agent)
- den Hash
- und die MISP-Infos (über Felder wie
misp.events[0].infoetc.)
Der FIM-/Zeek-Trigger (Rule 100100) kann weiter existieren, aber du musst ihn nicht mehr als „Hauptalarm“ verwenden.
5. Fazit: Enrichment = neuer Alert, nicht Anreicherung des alten
Die Kerngedanken aus diesem Thread:
- Wazuh-Alerts werden nicht nachträglich verändert
- Integrationen wie MISP laufen asynchron und erzeugen neue Events
- Wenn du kontextreiche Threat-Intel-Alerts willst, musst du:
- dein Python-Integrationsskript als „Daten-Brücke“ nutzen
- alle relevanten Felder vom ersten Alert → in den zweiten Event kopieren
- den zweiten Alert (MISP-Match) als entscheidenden SOC-Alarm betrachten
https://wazuh.slack.com/archives/C0A933R8E/p1764345878325169