AWS WAF + Wazuh: Wie man „verflachte“ JSON-Header wieder brauchbar macht
Wer AWS WAF-Logs mit Wazuh auswertet, stößt früher oder später auf ein nerviges Detail: Arrays von Objekten werden vom JSON-Decoder „plattgemacht“ – und plötzlich ist die Zuordnung von Header-Name zu Header-Wert kaputt.
Genau das passierte Prathamesh Bakliwal, der WAF-Logs aus CloudWatch über das Wazuh-aws-s3-Modul einspeist. Die Felder waren zwar dekodiert – aber nicht so, wie er sie brauchte.
In diesem Beitrag schauen wir uns an:
- Woher das Problem kommt
- Welche Lösungsansätze Wazuh selbst bietet
- Wann Preprocessing mit
jqsinnvoller ist - Und wie man das Ganze konkret konfiguriert
Das Problem: JSON-Decoder & Arrays von Objekten
Ausgangslage:
- Logs stammen aus AWS WAF,
- werden über CloudWatch → aws-s3 wodle ins Wazuh-Backend geholt,
- und mit dem Wazuh JSON-Decoder verarbeitet.
Ein typischer Ausschnitt aus einem WAF-Log:
"httpRequest": {
"clientIp": "13.x.x.x",
"country": "IN",
"headers": [
{ "name": "user-agent", "value": "unirest-java/1.3.11" },
{ "name": "Host", "value": "api.taxbuddy.com" },
{ "name": "Content-Type", "value": "application/json" }
],
...
}
Was Wazuh daraus macht:
- Es erkennt das
headers-Array, - trennt alle
name-Felder in eine Liste, - und alle
value-Felder in eine andere Liste.
Ergebnis (vereinfacht):
httpRequest.headers.name = ["user-agent", "Host", "Content-Type", ...]httpRequest.headers.value = ["unirest-java/1.3.11", "api.taxbuddy.com", "application/json", ...]
🔻 Problem:
Die 1:1-Beziehung zwischen name und value geht verloren. Man weiß nicht mehr sicher, welcher Wert zu welchem Header gehört – und die Reihenfolge ist nicht garantiert stabil.
Das ist besonders bitter, wenn man genau bestimmte Header braucht, z. B.:
user-agenthostauthorization- spezielle API-Keys (z. B.
mongo-api-key)
Ursache: Standardverhalten des Wazuh JSON-Decoders
[Wazuh] Pablo erklärt es so:
Wenn Wazuh Arrays von Objekten verarbeitet, „flacht“ der JSON-Decoder die Struktur.
Alle name-Felder landen in einer Liste, alle value-Felder in einer anderen.
Die ursprüngliche Zuordnung geht dabei verloren.
Das ist kein Bug, sondern das momentane Design des Decoders – und es macht viele Dinge einfach, aber genau diesen Use-Case schwierig.
Lösungsweg 1: Custom Decoder in Wazuh (ohne zusätzliche Infrastruktur)
Wenn man bestimmte Felder gezielt extrahieren möchte, kann man das Problem innerhalb von Wazuh lösen – mit individuellen Decodern.
Pablo zeigt zwei Varianten:
1a) Nur die gewünschten Felder parsen (gezielt & schlank)
Hier werden gezielt wichtige Felder extrahiert, z. B.:
actionclientIpcountryuser-agenthosthttpVersionhttpMethod
Beispieldecoder:
<decoder name="aws-waf-child">
<parent>json</parent>
<prematch type="pcre2">webaclId":"arn:aws:wafv2</prematch>
<regex type="pcre2">
"action":"(\w+)".*?"clientIp":"([^"]+)","country":"([^"]+)"
.*?"name":"user-agent","value":"([^"]+)"
.*?"name":"(?i)host","value":"([^"]+)"
.*?"httpVersion":"([^"]+)","httpMethod":"(\w+)"
</regex>
<order>
waf_action, srcip, src_country,
http_user_agent, http_host,
protocol, http_method
</order>
</decoder>
Was hier passiert:
parent="json"→ knüpft an den normalen JSON-Decoder anprematch→ stellt sicher, dass nur WAF-Events mitwebaclIdbetroffen sindregex→ zieht die gewünschten Felder in der richtigen Reihenfolge rausorder→ weist die Match-Gruppen sprechenden Feldnamen zu
Resultat in wazuh-logtest:
waf_action = ALLOWsrcip = 13.x.x.xsrc_country = INhttp_user_agent = unirest-java/1.3.11http_host = api.taxbuddy.comprotocol = HTTP/1.1http_method = POST
Perfekt für Dashboards, Regeln, Alerts und SIEM-Korrelation.
1b) JSON behalten, aber einzelne Felder zusätzlich rausziehen
In manchen Fällen möchte man:
- die komplette JSON-Struktur behalten,
- aber einzelne Header trotzdem als eigene Felder haben.
Dann kann man so vorgehen:
- JSON als Ganzes durch den Standarddecoder verarbeiten
- Danach über mehrere Child-Decoder gezielt Felder extrahieren
Beispiel:
<decoder name="json_child">
<parent>json</parent>
<prematch>webaclId</prematch>
<plugin_decoder>JSON_Decoder</plugin_decoder>
</decoder>
<decoder name="json_child">
<parent>json</parent>
<regex type="pcre2">"accept-encoding","value":"(.*?)"</regex>
<order>accept-encoding</order>
</decoder>
<decoder name="json_child">
<parent>json</parent>
<regex type="pcre2">"Content-Type","value":"(.*?)"</regex>
<order>Content-Type</order>
</decoder>
<!-- u. a. für user-agent, mongo-api-key, etc. -->
Ergebnis in wazuh-logtest:
- Alle Standardfelder des JSON-Decoders bleiben erhalten, z. B.
httpRequest.clientIp
httpRequest.urihttpRequest.hostlabelsruleGroupList…
Zusätzlich gibt es z. B.:
Content-Type = application/jsonaccept-encoding = gzip- (und weitere, je nach Regex)
Diese Variante ist ideal, wenn man „das volle JSON“ behalten und gleichzeitig gezielt Schlüssel-Felder promoten möchte.
Lösungsweg 2: Preprocessing mit jq (für maximale Flexibilität)
[BlueWolfNinja Kevin Branch] bringt eine zweite Perspektive:
Das eigentliche Problem ist die Darstellung als Arrays von Objekten. Wenn man diese vorher umformt, werden sie für Wazuh viel besser handhabbar.
Strategie:
- Statt
headers = [ {name, value}, {name, value}, ... ] - transformiert man nach
headers.1.name,headers.1.value,headers.2.name,headers.2.value, …
Beispiel-Felder nach jq-Transform:
data.httpRequest.headers.1.name = "user-agent"data.httpRequest.headers.1.value = "unirest-java/1.3.11"data.httpRequest.headers.2.name = "Host"data.httpRequest.headers.2.value = "api.taxbuddy.com"
Damit bleibt die Zuordnung sauber und Wazuh kann ganz normal darauf decodieren.
Kevin stellt dafür ein fertiges jq-Filterfile bereit:
transform-arrays-of-objects-to-numbered-objects.jq
auf GitHub bei BlueWolfNinja/wazuh-resources
Beispiel-Ablauf (selbstverwaltete Umgebung):
- Script schreibt regelmäßig neue CloudWatch-Logs in
raw.json jq -cf transform-arrays-of-objects-to-numbered-objects.jq raw.json >> processed.json- Wazuh sammelt die Events aus
processed.jsonper<localfile>
Prathamesh’ Einwand:
Logs kommen aktuell direkt von CloudWatch in Wazuh – ohne Zwischenstation.
Kevins Antwort:
- Bei self-managed Wazuh (kein Wazuh Cloud) kann man auf dem Manager:
eigene Pull-Skripte nutzen,
aws-log-pulleinsetzen,- oder sich von
aws-s3.py/cloudwatchlogs.pyinspirieren lassen.
So entsteht eine Art „Vorverarbeitungspipeline“, ohne dass andere Server dazukommen müssen.
Wann welchen Ansatz wählen?
Wazuh-Custom-Decoder (Variante Pablo)
Geeignet, wenn:
- Du genau weißt, welche Felder du brauchst (User-Agent, Host, Action, IP, Country, …)
- Du möglichst wenig zusätzliche Infrastruktur möchtest
- Du alles direkt im Wazuh-Stack halten willst
Vorteile:
- Kein zusätzlicher Speicherort / keine extra Pipeline
- Einfache Wartung, solange sich das Logformat nicht stark ändert
- Ideal für zielgerichtete Security Use Cases
Preprocessing mit jq (Variante Kevin)
Geeignet, wenn:
- Du sehr viele unterschiedliche Felder / Header brauchst
- Du JSON-Strukturen generell „normen“ willst
- Du flexibel mit vielen AWS-Logformaten arbeitest
Vorteile:
- Saubere, stabile Feldstruktur für alle Tools, nicht nur Wazuh
- Bessere Weiterverarbeitung in anderen Systemen (z. B. SIEM, Data Lake)
- Gut kombinierbar mit Custom Decoders & Regeln
Fazit
Der Thread macht eine wichtige Eigenheit von Wazuh sichtbar:
- Der JSON-Decoder ist mächtig – aber Arrays von Objekten sind seine Schwachstelle.
- Gerade bei AWS WAF-Logs mit Header-Listen führt das zu unschönen, „verflachten“ Feldern.
Es gibt aber zwei solide Wege aus der Falle:
- Custom Decoder in Wazuh – ideal, wenn du klar definierte Schlüssel-Felder extrahieren willst.
- Vorverarbeitung mit
jq– ideal, wenn du die gesamte Struktur neu organisieren möchtest.
Je nach Umgebung (self-managed, Kubernetes, Wazuh Cloud oder Hybrid) kann man das eine oder andere Modell wählen – oder beides kombinieren.
https://wazuh.slack.com/archives/C0A933R8E/p1764058873307169
Mehr zum Wazuh Ambassador Program …
Quelle
Dieser Artikel stammt aus dem Wazuh-Blog von m.a.x. it (veröffentlicht am 9. Dezember 2025).
Unterstützung von m.a.x. it
Bei Einführung, Betrieb und Feintuning von Wazuh (SIEM) unterstützt Sie m.a.x. it mit SIEM-Services auf Open-Source-Basis.
Über m.a.x. it Die m.a.x. Informationstechnologie AG ist seit über 30 Jahren IT-Partner mittelständischer und großer Unternehmen in München und bietet maßgeschneiderte Lösungen und Services in den Bereichen Cloud, Cybersecurity, Netzwerk, Windows, Linux und Softwareentwicklung. Sie haben eine Frage zu diesem Artikel oder brauchen Unterstützung?
