2026-10-04 12:54:41 +02:00
|
|
|
# Docker Security fuer Wazuh
|
|
|
|
|
|
|
|
|
|
Ein eigenstaendiges Skript fuer **Debian-/Ubuntu-Docker-Hosts mit systemd**:
|
|
|
|
|
LXC, VM oder physischer Server. Die Dialogoberflaeche fragt nach Docker Listener,
|
|
|
|
|
regelmaessigen Image-Scans, Scanabstand und Einbeziehung gestoppter Container.
|
|
|
|
|
Ohne whiptail/dialog wird die Texteingabe verwendet. Vor Aenderungen ist `INSTALL`
|
|
|
|
|
erforderlich. Im Gegensatz zum LXC-Enrollment wird es direkt auf dem Docker-Host
|
|
|
|
|
ausgefuehrt und braucht keinen Proxmox-Host.
|
|
|
|
|
|
|
|
|
|
## Voraussetzungen
|
|
|
|
|
|
|
|
|
|
- Root, Python >= 3.9, Debian oder Ubuntu mit APT/systemd.
|
|
|
|
|
- Im Host-Modus: **Docker bereits installiert und lokal erreichbar** ueber
|
|
|
|
|
`/var/run/docker.sock`; nativer Wazuh-Agent bereits installiert und verbunden.
|
|
|
|
|
- Im Manager-Modus: nativer Wazuh-Manager. Kein Docker erforderlich.
|
|
|
|
|
- Zugriff auf offizielle APT-/PyPI-Quellen, Trivy-Datenbanken und CISA KEV.
|
|
|
|
|
|
|
|
|
|
Docker und Wazuh werden weder neu installiert noch registriert. Falls der Agent
|
|
|
|
|
fehlt, zuerst das vorhandene Enrollment-Skript verwenden. Rootless Docker,
|
|
|
|
|
Remote-Docker, Podman, Windows und Container mit einem darin laufenden Wazuh-Agent
|
|
|
|
|
sind nicht enthalten. Keine Container-Neustarts, Image-Pulls oder automatischen
|
|
|
|
|
Container-Updates. Der Agent bzw. Manager wird fuer seine neue Konfiguration
|
|
|
|
|
neu gestartet.
|
|
|
|
|
|
|
|
|
|
## 1. Einmal auf dem Wazuh-Manager
|
|
|
|
|
|
|
|
|
|
Direkt in dessen Konsole als root:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
curl -fsSL https://code.faboi.cloud/fabio/lxc-enroll/raw/branch/main/docker-security.sh \
|
|
|
|
|
-o /run/docker-security.sh && bash /run/docker-security.sh --manager-rules
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Das Skript ergaenzt `/var/ossec/etc/rules/docker_security_rules.xml`. Der vorhandene
|
|
|
|
|
JSON-Decoder wird genutzt. Keine neuen Decoder oder Discord-Webhook-Daten erforderlich.
|
|
|
|
|
Regel-ID-Kollisionen werden erkannt; vorhandene fremde Dateien werden nicht
|
|
|
|
|
ueberschrieben. `wazuh-analysisd -t` muss bestehen, bevor der Manager neu startet.
|
|
|
|
|
Bei Validierungs-/Neustartfehlern wird die vorherige Regeldatei wiederhergestellt.
|
|
|
|
|
|
|
|
|
|
## 2. Auf jedem Docker-Host
|
|
|
|
|
|
|
|
|
|
Direkt im LXC / in der VM / auf dem Server, der Docker betreibt:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
curl -fsSL https://code.faboi.cloud/fabio/lxc-enroll/raw/branch/main/docker-security.sh \
|
|
|
|
|
-o /run/docker-security.sh && bash /run/docker-security.sh
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Nur Voraussetzungen pruefen:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
bash /run/docker-security.sh --check
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Der offizielle Wazuh Docker Listener bekommt eine eigene Python-Umgebung unter
|
|
|
|
|
`/opt/wazuh-docker-security/listener-venv`. System-Python bleibt unveraendert.
|
|
|
|
|
Die offizielle Listener-Datei bekommt einen passenden Python-Interpreter in
|
|
|
|
|
der ersten Zeile. Ein unerwarteter Wrapper wird zur manuellen Pruefung abgelehnt.
|
|
|
|
|
Bei einem Wazuh-Paketupgrade kann diese Anpassung ueberschrieben werden;
|
|
|
|
|
anschliessend die Einrichtung erneut ausfuehren. Fuer Docker-Ereignisse gelten
|
|
|
|
|
weiterhin die eingebauten Wazuh-Docker-Regeln. Sie beweisen fuer sich allein
|
|
|
|
|
keinen erfolgreichen Angriff.
|
|
|
|
|
|
|
|
|
|
Fehlendes Trivy wird in Version **0.75.0** aus dem signierten offiziellen
|
|
|
|
|
APT-Repository installiert. Ein bereits installiertes APT-Paket ab Version
|
|
|
|
|
0.70.0 bleibt erhalten; aeltere Pakete werden vor Ausfuehrung abgelehnt und
|
|
|
|
|
muessen separat aktualisiert werden. Die im Maerz 2026 betroffenen Versionen
|
|
|
|
|
0.69.4-0.69.6 werden dadurch nicht verwendet. Es wird kein fremdes Installations-
|
|
|
|
|
Shellskript aus dem Netz ausgefuehrt. Python-Abhaengigkeiten kommen von PyPI;
|
|
|
|
|
Docker SDK 7.1.0, Requests >= 2.32.4 und urllib3 >= 2.2.3 werden im Venv genutzt.
|
|
|
|
|
|
|
|
|
|
Die bestehenden Agent-Einstellungen werden erhalten. XML mit mehreren
|
|
|
|
|
`ossec_config`-Bloecken und Kommentare wird unterstuetzt. Docker Listener und
|
|
|
|
|
eine JSON-Logquelle werden gezielt ergaenzt; ein erneuter Lauf erzeugt keine
|
|
|
|
|
doppelten Bloecke. Vor dem Agent-Neustart werden Agent-, Logcollector- und
|
|
|
|
|
Modules-Konfigurationen geprueft. Sicherungen liegen privat unter
|
|
|
|
|
`/var/backups/wazuh-docker-security/`. Bei Fehlern vor erfolgreichem Agent-
|
|
|
|
|
Neustart werden die Agent-Konfiguration und der angepasste Listener zurueckgesetzt.
|
|
|
|
|
Pakete und neu angelegte Scanner-Dateien werden nicht automatisch deinstalliert.
|
|
|
|
|
|
|
|
|
|
## Scans und Meldungen
|
|
|
|
|
|
|
|
|
|
Standard: Images **laufender Container**, alle **24 Stunden**, ein Image pro
|
|
|
|
|
Scan auch bei mehreren Containern mit diesem Image. Gestoppte Container koennen
|
|
|
|
|
zusaetzlich ausgewaehlt werden. Ungenutzte Images werden nicht gescannt.
|
|
|
|
|
Die erste Pruefung kann sofort im Hintergrund starten. Nach einem Neustart
|
|
|
|
|
startet der Timer wieder im gewaehlten Stundenabstand. Ein unmittelbarer erster
|
|
|
|
|
Scan startet nur bei Zustimmung; der Timer streut die Termine um bis zu zehn
|
|
|
|
|
Minuten. Datenbank-Downloads beim ersten Scan koennen dauern.
|
|
|
|
|
|
|
|
|
|
Gescannt werden die **tatsaechlichen lokalen Image-IDs**, ohne Registry-Fallback
|
|
|
|
|
oder Image-Pull. Ergebnisse enthalten erkannte High-/Critical-Schwachstellen
|
|
|
|
|
**auch ohne verfuegbaren Fix** sowie niedrigere Schweregrade, wenn die CVE im
|
|
|
|
|
CISA-KEV-Katalog steht. Das ist keine automatische Aussage ueber Ausnutzbarkeit
|
|
|
|
|
in der konkreten Anwendung. CISA KEV belegt bekannte Ausnutzung andernorts;
|
|
|
|
|
es belegt keinen Angriff auf diesen Host. Eine fehlende KEV-Zuordnung ist
|
|
|
|
|
keine Entwarnung und der Katalog ist keine vollstaendige Liste aller Exploits.
|
|
|
|
|
|
|
|
|
|
Unveraenderte Befunde werden bei regulaeren Folgescans nicht erneut in das
|
|
|
|
|
Event-Log geschrieben. Aenderungen an Schweregrad, Fix-Verfuegbarkeit, installierter
|
|
|
|
|
Version oder KEV-Status erzeugen ein neues Ereignis. Ein reiner Wechsel des
|
|
|
|
|
Image-Digests fuer denselben Containernamen wiederholt keine unveraenderte CVE.
|
|
|
|
|
Fehlgeschlagene Scans behalten bisherige Funde bei. Aus dem Scanumfang entfernte
|
|
|
|
|
Container werden als `out_of_scope` behandelt, nicht als behoben. Ein Scanner-
|
|
|
|
|
Problem wird beim Auftreten bzw. bei einer Aenderung gemeldet, statt jeden Lauf
|
|
|
|
|
erneut. Die komplette aktuelle relevante Inventarliste bleibt lokal verfuegbar.
|
|
|
|
|
|
|
|
|
|
| Gruppe / ID | Bedeutung | Level |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| `docker_security_review` / 110801 | Neuer/geaenderter High-/Critical-Fund zur Pruefung | 4 |
|
|
|
|
|
| `docker_security_kev` / 110802 | Erkannter Fund einer CVE in CISA KEV; priorisiert pruefen/mitigieren | 12 |
|
|
|
|
|
| `docker_security_health` / 110803 | Neue/geaenderte Scanner-Probleme | 7 |
|
2026-10-04 14:40:23 +02:00
|
|
|
| 110804 / 110805 | Fund verschwunden/ausserhalb Umfang oder Scanner erholt; nur Inventarstatus | 3 |
|
|
|
|
|
| 110806 | Status jedes abgeschlossenen Scans; nur Inventarstatus | 3 |
|
2026-10-04 12:54:41 +02:00
|
|
|
|
|
|
|
|
**Discord wird nicht neu eingerichtet.** Bestehende Wazuh-Integrationen koennen
|
|
|
|
|
je nach ihren Filtern bereits passende Level/Gruppen weiterleiten. Fuer Fabios
|
|
|
|
|
Ziel „nur wenn ich handeln muss“ muessen die Discord-Regeln anschliessend gezielt
|
|
|
|
|
auf relevante Sicherheitsereignisse zugeschnitten werden. Eine hohe CVSS-
|
|
|
|
|
Einstufung allein reicht nicht als Nachweis konkreter Ausnutzbarkeit. Fuer
|
|
|
|
|
Angriffserkennung sind zusaetzlich passende Anwendungslogs und ggf. Runtime-
|
|
|
|
|
Erkennung erforderlich; der Image-Scanner ersetzt diese nicht.
|
|
|
|
|
|
|
|
|
|
## Ergebnis pruefen
|
|
|
|
|
|
|
|
|
|
Auf dem Docker-Host:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
systemctl status wazuh-docker-security.service --no-pager -l
|
|
|
|
|
journalctl -u wazuh-docker-security.service -n 30 --no-pager
|
|
|
|
|
systemctl list-timers wazuh-docker-security.timer
|
|
|
|
|
python3 -m json.tool /var/lib/wazuh-docker-security/inventory.json
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Ein beendeter erfolgreicher `oneshot`-Dienst ist normalerweise **inactive (dead)**;
|
|
|
|
|
entscheidend ist der letzte Exitstatus und der naechste Timer-Termin.
|
|
|
|
|
Bei einem Fehler zeigt die Inventardatei `problems` bzw. `complete: false`.
|
|
|
|
|
|
|
|
|
|
In Wazuh **Explore / Discover**, Index `wazuh-alerts-*`:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
rule.groups:docker_security
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Review-Hinweise stehen im Alert-Index, **nicht automatisch im nativen
|
|
|
|
|
Vulnerability-Detection-Inventar**. Behoebene/out-of-scope Ereignisse Level 0
|
|
|
|
|
erscheinen nicht als normale Alerts. Docker-Ereignisse des Listeners sind
|
|
|
|
|
unter `rule.groups:docker` sichtbar. End-to-end-Empfang muss nach der ersten
|
|
|
|
|
Einrichtung dort geprueft werden; ein aktiver Agent allein beweist ihn nicht.
|
|
|
|
|
|
|
|
|
|
Dateien: `/opt/wazuh-docker-security/scan.py`,
|
|
|
|
|
`/etc/wazuh-docker-security/config.json`,
|
|
|
|
|
`/var/lib/wazuh-docker-security/{inventory,state,kev}.json`,
|
|
|
|
|
`/var/log/wazuh-docker-security/events.jsonl`. Lokale Einzelreports werden
|
|
|
|
|
nach 30 Tagen ohne Aktualisierung entfernt, Event-Logs per Logrotate rotiert.
|
|
|
|
|
Caches koennen Speicher belegen; bei Bedarf nach einem Scan
|
|
|
|
|
`trivy clean --cache-dir /var/lib/wazuh-docker-security/cache --all` nutzen.
|
|
|
|
|
|
|
|
|
|
Timer deaktivieren: `systemctl disable --now wazuh-docker-security.timer`.
|
|
|
|
|
Fuer spaetere Aenderungen das Skript erneut ausfuehren. Die Wahl „Nein“ laesst
|
|
|
|
|
bereits eingerichtete Komponenten unveraendert; sie deinstalliert/deaktiviert
|
|
|
|
|
sie nicht. Ein laufender Scan wird durch den Timer-Stopp nicht beendet.
|
|
|
|
|
|
|
|
|
|
## Grenzen
|
|
|
|
|
|
|
|
|
|
- Image-Inhalt, nicht schreibbare Container-Layer, gemountete Anwendungen/Volumes
|
|
|
|
|
oder dynamisch nachinstallierte Pakete. Keine vollstaendige Exploit-Erkennung.
|
|
|
|
|
- OS-/Bibliotheksabdeckung haengt von Trivy und den verfuegbaren Advisories ab.
|
|
|
|
|
- KEV wird taeglich aktualisiert; bei Netzfehlern wird der Cache genutzt. Ist er
|
|
|
|
|
aelter als sieben Tage, werden negative Zuordnungen als unbekannt behandelt.
|
|
|
|
|
- Transport ist nicht exactly-once: nach einem harten Abbruch oder Log-Wieder-
|
|
|
|
|
einlesen durch Wazuh koennen Ereignisse erneut erscheinen. Normale Scan-
|
|
|
|
|
Wiederholungen sind lokal dedupliziert.
|
|
|
|
|
- Ein sehr grosser Docker-Host kann das Dienstlimit von vier Stunden erreichen.
|
|
|
|
|
- Ein echter Docker-/Wazuh-Lauf ist noch ausstehend. Lokal geprueft sind Syntax,
|
|
|
|
|
Konfigurationserhalt, Rule-ID-Kollisionen, Scan-Ausgabe und Fehler-/Dedup-Faelle.
|
|
|
|
|
|
|
|
|
|
## Offizielle Quellen
|
|
|
|
|
|
|
|
|
|
- [Wazuh Docker Listener](https://documentation.wazuh.com/current/user-manual/capabilities/container-security/monitoring-docker.html)
|
|
|
|
|
- [Wazuh und Trivy](https://wazuh.com/blog/container-image-security-with-wazuh-and-trivy/)
|
|
|
|
|
- [Wazuh JSON-Decoder](https://documentation.wazuh.com/current/user-manual/ruleset/decoders/json-decoder.html)
|
|
|
|
|
- [Trivy-Installation](https://trivy.dev/docs/latest/getting-started/installation/)
|
|
|
|
|
- [Trivy Image-Quellen](https://trivy.dev/docs/latest/guide/target/container_image/)
|
|
|
|
|
- [Aqua: Trivy-Vorfall Maerz 2026](https://www.aquasec.com/blog/trivy-supply-chain-attack-what-you-need-to-know/)
|
|
|
|
|
- [CISA KEV](https://www.cisa.gov/known-exploited-vulnerabilities-catalog)
|
2026-10-04 14:40:23 +02:00
|
|
|
|
|
|
|
|
## Katalogabruf und gezielte Benachrichtigungen
|
|
|
|
|
|
|
|
|
|
Wenn die CISA-Webseite mit 403 antwortet, wird der offizielle Spiegel unter
|
|
|
|
|
`github.com/cisagov/kev-data` genutzt. Anzahl, CVE-IDs und Veröffentlichungsdatum
|
|
|
|
|
werden geprüft; ein über 14 Tage alter Spiegel wird abgelehnt. Der Cache gilt
|
|
|
|
|
maximal sieben Tage als frisch. Ein fehlender Katalog bedeutet weiterhin
|
|
|
|
|
„unbekannt“, nicht „keine Ausnutzung“.
|
|
|
|
|
|
|
|
|
|
Scanner-Status, Behebungen und Erholungen werden als Level-3-Inventarereignisse
|
2026-10-04 14:42:02 +02:00
|
|
|
indexiert. Diese Ereignisse sind keine Discord-Benachrichtigungen. Eine separat und privat eingerichtete Benachrichtigungslogik kann aktuelle
|
|
|
|
|
OS-Schwachstellen sowie Image-Ereignisse und positive Malware-Erkennungen verarbeiten.
|