Den Docker-Socket absichern - das unterschätzte Sicherheitsrisiko
Den Docker-Socket absichern - das unterschätzte Sicherheitsrisiko
Der Docker-Socket /var/run/docker.sock ist effektiv ein root-Shell auf dem Host — wer ihn in einen Container mountet, gibt diesem Container vollen Host-Zugriff.
Warum der Socket so mächtig ist
# Container mit Socket-Zugriff kann auf dem Host alles tun:
docker run -v /var/run/docker.sock:/var/run/docker.sock alpine \
docker run -v /:/host --rm alpine chroot /host # Host-Filesystem vollständig gemountet
- Wer den Docker-Socket hat, kann:
- Neue Container starten (auch privilegierte)
- Host-Verzeichnisse mounten
- Laufende Container inspecten (inkl. ENV-Variablen mit Secrets)
- Den Docker-Daemon selbst steuern
Wer den Socket wirklich braucht
Einige legitime Tools brauchen den Socket:
- Traefik: Auto-Discovery von Containern
- Portainer: Container-Management
- Watchtower: Automatische Image-Updates
- Dozzle: Log-Viewer
Die Frage ist nicht, ob man ihn mountet, sondern wie man das Risiko begrenzt.
Mitigation 1: Socket-Proxy (empfohlen)
tecnativa/docker-socket-proxy sitzt zwischen Tool und Socket und exposed nur bestimmte API-Endpunkte:
services:
socket-proxy:
image: tecnativa/docker-socket-proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
CONTAINERS: 1 # Erlaubt: /containers/*
SERVICES: 0 # Verboten: /services/*
TASKS: 0
NETWORKS: 1
IMAGES: 0 # Verboten: Images pullen/pushen
INFO: 1
PING: 1
POST: 0 # Alle POST-Requests (Schreib-Ops) verboten
networks:
- socket-proxy # Isoliertes Netzwerk
traefik:
image: traefik:v3.0
environment:
DOCKER_HOST: tcp://socket-proxy:2375 # Via Proxy, nicht direkt
networks:
- socket-proxy
- public
networks:
socket-proxy:
internal: true # Kein Internet-Zugriff aus diesem Netz
public:
Traefik sieht nur Container-Listen, kann aber keine neuen Container starten oder Images pullen.
Mitigation 2: Rootless Docker
# Docker im Rootless-Modus installieren
dockerd-rootless-setuptool.sh install
# Socket liegt dann unter:
$XDG_RUNTIME_DIR/docker.sock
Im Rootless-Modus läuft der Docker-Daemon ohne root-Rechte. Ein kompromittierter Container kann nicht auf root-Ressourcen des Hosts zugreifen.
Docker TCP: niemals ohne TLS
# GEFÄHRLICH: Ungesicherter TCP-Zugriff
dockerd -H tcp://0.0.0.0:2375 # Jeder im Netz hat root-Zugriff
# Sicher: Mit TLS-Zertifikaten
dockerd -H tcp://0.0.0.0:2376 --tlsverify \
--tlscacert=ca.pem \
--tlscert=server-cert.pem \
--tlskey=server-key.pem
Port 2375 (ungesichert) sollte niemals öffentlich erreichbar sein. Wer Docker remote verwalten will: SSH-Tunneling ist die sichere Alternative.
# Remote Docker via SSH (kein offener Port nötig)
docker -H ssh://user@remote-host ps
DOCKER_HOST=ssh://user@remote-host docker ps
Wer darf auf den Socket zugreifen?
ls -la /var/run/docker.sock
# srw-rw---- root docker
# Nur Mitglieder der docker-Gruppe
usermod -aG docker deployuser
Die docker-Gruppe ist für alle praktischen Zwecke gleichwertig mit root. Mitgliedschaft nur für vertrauenswürdige Accounts.
Socket-Zugriff im Audit-Log
# Mit auditd überwachen wer den Socket nutzt
auditctl -w /var/run/docker.sock -p rwxa -k docker-socket
ausearch -k docker-socket
Checkliste Socket-Sicherheit
- Socket-Proxy für Tools wie Traefik und Portainer
- Kein
:2375offen ohne TLS - Rootless Docker wo möglich
docker-Gruppe minimal besetzt- Keine Produktions-Apps bekommen den Socket
Der Docker-Socket ist das wertvollste Angriffsziel auf einem Docker-Host — und er wird in vielen Setups sorglos gemountet.
Weiterführend
Wer sich tiefer mit Linux-Sicherheit, Dateiberechtigungen und Systemhärtung befasst, findet passende Artikel auf nolr.nexon.cyou.