Zurück zum Blog

Wazuh SIEM Security Hardening

Wazuh SIEM Security Hardening

Datum 29. Januar 2026
Kategorie Security
Lesezeit 12 Minuten

Ausgangslage & identifizierte Probleme

Nach dem initialen Deployment des Wazuh SIEM v4.14.1 wurde bei einer Sicherheitsanalyse festgestellt, dass die benutzerdefinierte Konfiguration nicht korrekt angewendet wurde. Der laufende Wazuh-Manager verwendete die Standard-Konfiguration statt der angepassten Version aus dem Repository.

Kritische Probleme gefunden:
  • Config-Drift: Die ossec.conf wurde an einen falschen Mount-Pfad gemountet und daher nicht geladen
  • SMTP fehlerhaft: E-Mail-Server zeigte auf nicht erreichbaren Host
  • Keine Push-Alerts: Keine Echtzeit-Benachrichtigung bei Security Events
  • Active Response deaktiviert: Automatische IP-Blockierung war nicht aktiv
  • FIM eingeschränkt: Nur Wazuh-eigene Konfig wurde überwacht, nicht die Docker-Infrastruktur
  • Fehlende Rules: Referenzierte Custom-Rule-Dateien existierten nicht

Neue Architektur

Die aktualisierte Wazuh-Konfiguration implementiert ein mehrstufiges Sicherheitskonzept mit Multi-Channel-Benachrichtigungen und automatischer Bedrohungsabwehr.

Wazuh SIEM - Erweiterte Architektur ┌─────────────────────────────────────────────────────────────────┐ │ │ │ Log-Quellen Wazuh Manager │ │ ───────────── ────────────── │ │ /host-logs/auth.log ──┐ │ │ /host-logs/syslog ──┤ ┌──────────────────┐ │ │ /host-logs/kern.log ──┤───▶│ Log Analysis │ │ │ /traefik-logs/access ──┤ │ + JSON Decoder │ │ │ /fail2ban-logs ──┘ └────────┬─────────┘ │ │ │ │ │ ▼ │ │ ┌──────────────────┐ │ │ │ Custom Rules │ │ │ │ ├ matzka_rules │ │ │ │ ├ docker_rules │ │ │ │ └ traefik_rules │ │ │ └────────┬─────────┘ │ │ │ │ │ ┌──────────┼──────────┐ │ │ ▼ ▼ ▼ │ │ ┌───────────┐ ┌─────────┐ ┌────────────┐ │ │ │ Active │ │ Email │ │ Gotify │ │ │ │ Response │ │ Alert │ │ Push │ │ │ │ (Block IP)│ │ Lv 10+ │ │ Lv 7+ │ │ │ └───────────┘ └─────────┘ └────────────┘ │ │ │ │ FIM-Überwachung: /var/ossec/etc + /docker-configs │ │ │ └─────────────────────────────────────────────────────────────────┘

Netzwerk-Konnektivität

Der Wazuh-Manager ist mit vier Docker-Netzwerken verbunden:

Netzwerk Zweck
security (internal) Kommunikation mit Indexer und Dashboard
monitoring Prometheus Exporter Metriken
smtp-internal E-Mail-Benachrichtigungen via SMTP-Relay
updates Gotify Push-Notifications

Gotify Push-Alerts

Wazuh unterstützt Custom Integrations über Python-Scripts. Das neue custom-gotify Script empfängt Alert-JSON und sendet formatierte Push-Notifications an den Gotify-Server.

Gotify Integration

Level 7+ Alerts werden als Push-Notification an gotify.matzka.cloud gesendet. Die Priorität wird automatisch aus dem Wazuh Alert-Level berechnet.

Prioritäts-Mapping

Wazuh Level Schweregrad Gotify Priorität Beispiele
12+ CRITICAL 9 (höchste) SSO Brute-Force, Account Compromise
10-11 HIGH 8 Brute-Force Angriffe, SQL Injection
7-9 WARNING 5 Auth-Fehler, Scanner-Aktivität, 5xx Fehler

Notification-Format

Jede Gotify-Nachricht enthält:

  • Titel: Schweregrad + Rule ID
  • Beschreibung: Alert-Text von der Wazuh-Rule
  • Details: Level, Agent, Source-IP, Gruppen, Zeitstempel
  • Format: Markdown für optimale Lesbarkeit

ossec.conf Konfiguration

<!-- Gotify Push Notification Integration -->
<integration>
  <name>custom-gotify</name>
  <hook_url>http://gotify:80/message?token=GOTIFY_WAZUH_TOKEN</hook_url>
  <level>7</level>
  <alert_format>json</alert_format>
</integration>
Hinweis: Das Token wird als Environment-Variable GOTIFY_WAZUH_TOKEN über docker-compose.yml injiziert. Das Script selbst enthält keine Credentials.

Active Response - Automatische IP-Blockierung

Active Response blockiert automatisch IP-Adressen, die verdächtige Aktivitäten zeigen. Drei Stufen wurden konfiguriert:

Stufe 1: SSH Brute-Force (10 Minuten)

Rules 5710-5716
Trigger: Mehrere fehlgeschlagene SSH-Login-Versuche
Aktion: IP wird für 10 Minuten via firewall-drop blockiert
Quelle: /host-logs/auth.log

Stufe 2: Authentication Failures (5 Minuten)

Rules 5503-5504
Trigger: Wiederholte Authentifizierungsfehler auf Systemebene
Aktion: IP wird für 5 Minuten blockiert
Quelle: /host-logs/auth.log

Stufe 3: Web-Service Brute-Force (15 Minuten)

Rules 100002, 100012, 100021, 100041, 100051
Trigger: Brute-Force-Angriffe auf Web-Services
Aktion: IP wird für 15 Minuten blockiert
Betroffene Services:
  • Nextcloud (next.matzka.cloud) - 5 Fehler in 2 Min
  • Authentik SSO (auth.matzka.cloud) - 3 Fehler in 2 Min
  • Grafana (monitor.matzka.cloud) - 3 Fehler in 1 Min
  • PostfixAdmin (admin.matzka.cloud) - 3 Fehler in 2 Min
  • Roundcube (webmail.matzka.cloud) - 5 Fehler in 5 Min
Admin-IP Whitelist: Die Admin-IP ist in der <white_list> Konfiguration hinterlegt und wird niemals von Active Response blockiert.

Custom Detection Rules

Drei Custom-Rule-Dateien wurden erstellt, die spezifisch auf die matzka.cloud Infrastruktur zugeschnitten sind:

matzka_rules.xml (ID 100001-100299)

Service-spezifische Erkennung für alle Web-Services:

ID-Range Service Erkennungen
100001-100009 Nextcloud Auth-Fehler, Brute-Force, Forbidden, Admin-Zugriff
100010-100019 Grafana Unauthorized, Login-Fehler, Brute-Force
100020-100029 Authentik SSO Login-Fehler, Brute-Force (CRITICAL), Admin-Panel
100030-100039 n8n Auth-Fehler, Unauthorized API
100040-100059 PostfixAdmin, Roundcube Login-Fehler, Brute-Force
100060-100069 WebApp Scanner-Erkennung, SQL Injection, XSS
100090-100099 Traefik (Basis) DDoS-Erkennung, 5xx-Fehler, SSL-Probleme
100100-100199 Übergreifend Login nach Failures (Compromise), Reconnaissance
100200-100299 False Positives Rootcheck-Suppressions (verifiziert)

docker_rules.xml (ID 100300-100399)

Docker-spezifische Erkennung:

100300 - Container gestoppt (Level 5)
100301 - Container Restart Loop: 3+ Neustarts in 5 Min (Level 10)
100302 - OOM Killed: Kernel OOM-Killer hat Container-Prozess beendet (Level 10)
100320 - Docker Daemon Error (Level 8)
100321 - Image Pull fehlgeschlagen (Level 7)
100322 - Volume Mount Fehler (Level 8)
100340 - Privilegierter Container gestartet (Level 10, MITRE T1611)
100341 - Neuer Container erstellt (Level 3, Audit Trail)
100342 - Netzwerk-Verbindung (Level 3, Audit Trail)

traefik_rules.xml (ID 100400-100499)

Traefik Reverse-Proxy Erkennung:

100400 - Backend Service nicht erreichbar (502/503, Level 7)
100401 - Persistenter Backend-Fehler: 5+ Fehler in 2 Min (Level 10)
100402 - Gateway Timeout 504 (Level 6)
100420 - Plain HTTP auf sensitivem Service (Level 5)
100421 - Veraltete TLS-Version 1.0/1.1 (Level 6)
100422 - Unbekannter Host / Host-Header-Attack (Level 7)
100423 - Scanner: 10+ unbekannte Host-Anfragen (Level 9)
100440 - Path Traversal Versuch (Level 9, MITRE T1083)
100441 - Verdächtiger User-Agent / Scanner-Tool (Level 6)
100460 - Excessive 4xx: 20+ Fehler in 1 Min (Level 8)
MITRE ATT&CK Mapping: Alle kritischen Rules sind mit MITRE ATT&CK IDs versehen (T1110 Brute Force, T1190 Exploit Public-Facing App, T1611 Escape to Host, T1498 DoS, T1083 File Discovery, T1595 Active Scanning).

File Integrity Monitoring (FIM)

Das FIM wurde erheblich erweitert. Neben der Wazuh-eigenen Konfiguration werden jetzt auch alle Docker Compose Konfigurationsdateien überwacht.

Überwachte Verzeichnisse

Pfad im Container Quelle Inhalt
/var/ossec/etc Wazuh-intern Manager-Konfiguration, Rules, Decoders
/docker-configs Host: /opt/docker/compose Docker Compose Files, Traefik Config, .env Dateien

Ausnahmen (Ignore-List)

  • /var/ossec/logs, /var/ossec/queue, /var/ossec/var - Häufig ändernde Wazuh-Dateien
  • /docker-configs/traefik/logs - Access Logs (werden separat analysiert)
  • /docker-configs/traefik/acme.json - Let's Encrypt Zertifikate (ändern sich bei Renewal)
  • Pattern: .log$|.swp$|.tmp$ - Temporäre Dateien

FIM-Konfiguration

<syscheck>
  <disabled>no</disabled>
  <frequency>43200</frequency>  <!-- 12 Stunden -->
  <scan_on_start>yes</scan_on_start>

  <!-- Wazuh-eigene Konfiguration -->
  <directories check_all="yes" realtime="yes" report_changes="yes">
    /var/ossec/etc
  </directories>

  <!-- Docker Compose Konfigurationen -->
  <directories check_all="yes" realtime="yes" report_changes="yes">
    /docker-configs
  </directories>

  <ignore>/docker-configs/traefik/logs</ignore>
  <ignore>/docker-configs/traefik/acme.json</ignore>
</syscheck>

Custom Decoders

Traefik JSON Access Log Decoder

Traefik schreibt Access Logs im JSON-Format. Ein Custom Decoder (traefik_decoder.xml) nutzt Wazuhs eingebauten JSON-Decoder zur Extraktion aller Felder.

<decoder name="traefik-accesslog">
  <prematch>^{"ClientAddr":|^{"StartUTC":|^{"level":</prematch>
  <plugin_decoder>JSON_Decoder</plugin_decoder>
</decoder>

Extrahierte Felder

Der Decoder stellt folgende Felder für die Custom Rules bereit:

  • ClientHost - Source IP des Clients
  • RequestHost - Angefragter Hostname (z.B. next.matzka.cloud)
  • RequestPath - URL-Pfad
  • RequestMethod - HTTP-Methode
  • DownstreamStatus - HTTP Status Code
  • TLSVersion - Verwendete TLS-Version
  • RouterName - Traefik-Router der den Request bedient
  • Duration - Request-Dauer in Nanosekunden

Deployment

Behobene Konfigurationsprobleme

Problem Vorher Nachher
ossec.conf Mount /wazuh-config-mount/etc/ossec.conf:ro (nicht geladen) /var/ossec/etc/ossec.conf (korrekt)
SMTP Server Nicht erreichbarer Host smtp-relay (interner SMTP-Gateway)
E-Mail Empfänger Generische Admin-Adresse Korrekte Admin-E-Mail-Adresse
Windows Registry Unnötige Windows-Einträge in FIM Entfernt (reine Linux-Umgebung)

Neue Volume-Mounts

volumes:
  # Konfiguration (korrekt gemountet)
  - ./wazuh-config/manager/ossec.conf:/var/ossec/etc/ossec.conf
  - ./wazuh-config/manager/rules:/var/ossec/etc/rules/custom:ro
  - ./wazuh-config/manager/decoders:/var/ossec/etc/decoders/custom:ro
  - ./wazuh-config/manager/integrations/custom-gotify:/var/ossec/integrations/custom-gotify:ro

  # Log-Quellen
  - /var/log:/host-logs:ro
  - ../traefik/logs:/traefik-logs:ro
  - /var/log/fail2ban.log:/fail2ban-logs/fail2ban.log:ro

  # Docker-Konfigurationen fuer FIM
  - /opt/docker/compose:/docker-configs:ro

Dateistruktur nach Update

security/wazuh-config/manager/
├── ossec.conf                    # Hauptkonfiguration (v4.14.1)
├── decoders/
│   └── traefik_decoder.xml       # Traefik JSON Decoder
├── integrations/
│   └── custom-gotify             # Gotify Push-Script (Python)
└── rules/
    ├── matzka_rules.xml          # Service-spezifische Rules (100001-100299)
    ├── docker_rules.xml          # Docker Container Rules (100300-100399)
    └── traefik_rules.xml         # Traefik Reverse-Proxy Rules (100400-100499)

Verifizierung

Nach dem Deployment sollten folgende Punkte geprüft werden:

1. Konfiguration geladen

# Prüfe ob die korrekte Config geladen wurde
docker exec wazuh-manager cat /var/ossec/etc/ossec.conf | grep smtp_server
# Erwartung: smtp-relay

2. Custom Rules aktiv

# Prüfe ob alle Rule-Dateien vorhanden sind
docker exec wazuh-manager ls /var/ossec/etc/rules/custom/
# Erwartung: matzka_rules.xml  docker_rules.xml  traefik_rules.xml

3. Log-Analyse testen

# Starte den Log-Test-Modus
docker exec -it wazuh-manager /var/ossec/bin/wazuh-logtest

# Beispiel-Input (Traefik JSON):
# {"ClientHost":"1.2.3.4","RequestHost":"next.matzka.cloud","RequestPath":"/login","DownstreamStatus":401}
# Erwartung: Rule 100001 matched (Nextcloud Auth-Fehler)

4. Gotify Push testen

# Generiere einen Test-Alert und prüfe Gotify
# Methode: Mehrere fehlgeschlagene Logins auslösen
# Gotify-App sollte Push-Notification mit Severity und Details empfangen

5. Active Response verifizieren

# Prüfe ob Active Response aktiv ist
docker exec wazuh-manager /var/ossec/bin/wazuh-control info
# active-response: enabled

Zusammenfassung der Verbesserungen

Implementierte Sicherheitsverbesserungen:
  • ossec.conf Mount-Pfad korrigiert - Konfiguration wird jetzt korrekt geladen
  • SMTP-Konfiguration repariert - E-Mail-Alerts funktionieren
  • Gotify Push-Integration - Echtzeit-Alerts ab Level 7
  • 3-stufiges Active Response - Automatische IP-Blockierung
  • 28 Custom Rules in 3 Dateien - Abdeckung aller matzka.cloud Services
  • Traefik JSON Decoder - Vollständige Reverse-Proxy Log-Analyse
  • Erweitertes FIM - Docker Compose Konfigurationen werden überwacht
  • MITRE ATT&CK Mapping - Standardisierte Bedrohungsklassifizierung