CrowdStrike-Logs in Wazuh: Wenn Alerts im Archiv sichtbar sind, aber wegen full_log nie im Index landen

Mah Wen Qiang wollte CrowdStrike-Logs sauber in Wazuh integrieren:

  • Logs kommen aus: /var/log/crowdstrike/falconhoseclient/output
  • Multiline-JSON wird über multi-line-regex eingesammelt
  • Es existiert bereits eine Custom Rule 195009, die einen schönen Alert erzeugt:

„Crowdstrike alert – User authentication success – UserId: …“

Im archives.json ist das Event da – mit sauberem JSON-Decoder und data.metadata / data.event Feldern.

Aber:
Im Wazuh „Discover“/„Kibana“/„OpenSearch Dashboards“ taucht der Alert nicht auf.
Gleichzeitig meldet Filebeat:

mapper_parsing_exception … failed to parse field [full_log] of type [text]

Später tritt derselbe Fehler auch bei Sysmon/Windows-Events auf.
Was passiert hier genau – und wie behebt man das sauber?

1. Der Anfang: CrowdStrike-Log ist da – aber nur im Archiv

Konfiguration für die Logsammlung:

<localfile>
  <log_format>multi-line-regex</log_format>
  <location>/var/log/crowdstrike/falconhoseclient/output</location>
  <multiline_regex replace="wspace">^{</multiline_regex>
</localfile>

Damit:

  • werden Multiline-JSON-CrowdStrike-Events zu einem Log zusammengefasst
  • Wazuh dekodiert das als JSON (decoder: "json")
  • Custom Rule 195009 triggert korrekt (Level 3, Gruppe crowdstrikeauthentication_success)

Im archives.json sieht man z. B.:

"decoder": { "name": "json" },
"data": {
  "metadata": { ... },
  "event": {
    "UserId": "...",
    "UserIp": "...",
    "OperationName": "userAuthenticate",
    ...
  }
}

Also: Sammlung & Dekodierung funktionieren.

Aber: Der Alert taucht nicht im Index wazuh-alerts-* auf.

2. Die eigentliche Ursache steckt in Filebeat & dem Feld full_log

Der entscheidende Hinweis kommt aus /var/log/filebeat/filebeat:

"mapper_parsing_exception","reason":"failed to parse field [full_log] of type [text]"
...
"Can't get text on a START_OBJECT"

Übersetzt:

  • Das Mapping sagt: full_log ist vom Typ text (also ein einfacher String).
  • Der tatsächlich gesendete Wert von full_log ist aber kein String, sondern ein JSON-Objekt (START_OBJECT).
  • OpenSearch versucht, daraus Text zu lesen – scheitert – und verwirft das gesamte Dokument.
  • Ergebnis: Du siehst den Alert im Archiv, aber nie im Index / Dashboard.

Stuti erklärt es sehr klar:

  • In den Wazuh-Index-Templates ist full_log immer als text definiert.
  • Es darf deshalb nur reine Zeichenketten enthalten – keine Objekte, keine Arrays.
  • Wenn ein Log so verarbeitet wird, dass full_log zu einem JSON-Objekt wird, fliegt das Event beim Indexieren raus.

Genau das ist bei:

  • CrowdStrike-Logs
  • und später auch bei bestimmten Sysmon-/Windows-Events

passiert.

3. Warum passiert das ausgerechnet bei CrowdStrike & Sysmon?

Typischer Flow:

  1. Log kommt als JSON oder wird intern in eine JSON-Struktur übersetzt (z. B. EventChannel / Sysmon / CrowdStrike-API-Output).
  2. Wazuh dekodiert das Ereignis → Füllt data.* sauber.
  3. Zusätzlich wird das „volle“ Ereignis auch in full_log gespeichert.

Wenn dabei aus Versehen ein Objekt statt eines Strings in full_log landet, sieht das für den Indexer so aus:

"full_log": {
  "win": {
    "eventdata": { ... },
    "system": { ... }
  }
}

oder:

"full_log": {
  "metadata": { ... },
  "event": { ... }
}

Und genau dann knallt es mit:

"Can't get text on a START_OBJECT"

Denn ein text-Feld darf nicht { ... } sein.

4. Der kurzfristige Fix: no_full_log auf problematische Logs anwenden

Mah hat zunächst sauber reagiert:

<options>no_full_log</options>

in der CrowdStrike-Regelgruppe gesetzt.

Ergebnis:

  • full_log wird für diese Events nicht befüllt
  • damit erreicht nie ein „falscher“ Wert das Mapping
  • der Indexer akzeptiert die Events wieder
  • Alerts tauchen im Dashboard auf

Das ist absolut legitim – und oft die beste Lösung, wenn:

  • die wichtigen Felder bereits in data.* vorhanden sind
  • man full_log nicht unbedingt braucht
  • Logs sehr lang oder verschachtelt sind (CrowdStrike, Sysmon, etc.)

5. Der zweite Fall: Sysmon & Windows EventChannel

Später tritt derselbe Fehler bei gewissen Sysmon-Events (z. B. Event 15) auf:

"failed to parse field [full_log] of type [text] ..."
"Can't get text on a START_OBJECT..."

Auch hier:

  • Die Auswertung zeigt, dass full_log bei bestimmten Windows-/WEF-/Sysmon-Events als Objekt interpretiert wird.
  • Standard-Regeln aus dem Ruleset (z. B. 67017 für „A network share was accessed“) triggern ohne no_full_log.
  • Das führt dazu, dass genau diese Events bei der Indexierung scheitern.

Stuti weist darauf hin:

Dein no_full_log wirkt nur auf deine eigenen Regeln.
Wenn eine Default-Regel aus dem Standard-Ruleset triggert und full_log befüllt, bekommst du trotzdem die Mapping-Fehler.

6. Die saubere, langfristige Lösung: Standard-Regeln kopieren, überschreiben, no_full_log hinzufügen

Mahs finaler Fix sieht so aus:

  1. Bestimmte Default-Regelfiles werden im ossec.conf excluded: <rule_exclude>ruleset/rules/0595-win-sysmon_rules.xml</rule_exclude> <rule_exclude>ruleset/rules/0810-sysmon_id_3.xml</rule_exclude> <rule_exclude>ruleset/rules/0840-win_event_channel.xml</rule_exclude>
  2. Die betreffenden Regeln werden nach /var/ossec/etc/rules/ kopiert (als Custom Rules).
  3. In den kopierten Regeln wird jeweils ergänzt: <options>no_full_log</options>
  4. Wenn eine Default-Regel überschrieben wird, muss sie das Attribut haben: <rule id="67017" overwrite="yes" level="3"> ... <options>no_full_log</options> </rule>
  5. Wazuh Manager neu laden / neustarten.

Danach:

  • Nutzen die Events weiterhin die bekannten Default-Regellogiken.
  • full_log wird aber bei diesen spezifischen (problematischen) Events nicht mehr befüllt.
  • Die Mappingfehler verschwinden vollständig.
  • Alerts erscheinen zuverlässig im Index & im Dashboard.

7. Wichtige Klarstellungen

Keine gute Idee: das Mapping von full_log ändern

  • full_log ist bewusst als text definiert.
  • Ihn in object oder nested zu ändern würde:
    • Wazuh-Templates brechen
    • Konflikte mit bestehenden Indizes verursachen
    • Reindexing erzwingen
    • zukünftige Updates erschweren

Stuti betont:
Die richtige Lösung ist, dafür zu sorgen, dass full_log IMMER ein String bleibt – oder für bestimmte Events gar nicht gesetzt wird.

no_full_log ist gezielt einsetzbar

Es gibt 3 Varianten, wie du es nutzen kannst:

  1. In einzelnen Custom-Regeln
  2. In kopierten & überschriebenen Default-Regeln (overwrite="yes")
  3. Oder in eigenen Rule-Gruppen, die sehr „fette“ JSON- oder WEF-/Sysmon-Events behandeln.

8. Fazit

Der Thread rund um CrowdStrike und Sysmon zeigt:

  • Die Pipeline hat funktioniert – Sammlung, Dekodierung, Rule-Matching war korrekt.
  • Der Fehler lag nicht bei der Multiline-Konfiguration oder beim Decoder,
    sondern beim letzten Schritt: Indexierung des Feldes full_log.
  • Sobald full_log kein String, sondern ein Objekt oder Array wird, werfen Filebeat/Indexer das Event weg.
  • Mit <options>no_full_log</options> auf den richtigen Regeln (inkl. überschriebenen Default-Regeln) ist das Problem sauber gelöst – ohne Mapping-Hacks, ohne Schema-Brüche.

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

Mehr zu Wazuh …

Mehr zum Wazuh Ambassador Program …