Container Escape - Ausbruch aus Docker/Kubernetes-Containern
Container Escape bezeichnet Techniken mit denen ein Angreifer aus einem Container in den Host oder andere Container ausbrechen kann. Häufige Vektoren: privilegierte Container (--privileged), fehlerhaft gemountete Host-Verzeichnisse, unsichere cgroup/namespace-Konfiguration, Docker-Socket-Mount, Kernel-Exploits und Runc-CVEs. Schutz: unprivilegierte Container, read-only Filesystems, Seccomp/AppArmor-Profile, keine privilegierten Ports unter 1024.
Container Escape bezeichnet den Ausbruch aus der Container-Sandbox auf das Host-System oder in andere Container. Container bieten Isolation via Linux-Namespaces und cgroups - aber diese Isolation ist nicht so stark wie Hardware-Virtualisierung. Fehlkonfigurationen oder Schwachstellen können diese Isolation aufheben.
Container-Isolation und ihre Grenzen
Wie Container-Isolation funktioniert:
Linux-Container basieren auf:
□ Namespaces: Prozess-, Netzwerk-, Dateisystem-Isolation
□ cgroups: Ressourcen-Limits (CPU, Memory)
□ Capabilities: granulare Berechtigungen statt root/non-root
□ Seccomp: erlaubte Syscalls whitelist
□ AppArmor/SELinux: Mandatory Access Control
Unterschied zu VMs:
VM: Hypervisor → vollständige Hardware-Emulation → starke Isolation
Container: gemeinsamer Kernel mit Host → dünnere Isolation!
→ Container-Escape = Kernel-Angriff (VM-Escape: deutlich schwerer)
Docker-Privilege-Modell:
Standard-User im Container: root (UID 0) im Container-Namespace
ABER: root im Container ≠ root auf Host
→ Namespace-Mapping: Container-root → Host-UID (z.B. 100000)
→ Ausnahme: wenn kein user-namespace → Container-root = Host-root!
Container-Escape-Techniken
Vektor 1 - Privilegierter Container (--privileged):
docker run --privileged nginx
→ Container hat ALLE Linux-Capabilities
→ Kann: neue Geräte mounten, raw-sockets nutzen, cgroups manipulieren
Triviale Escape-Methode:
# Von innen im --privileged Container:
mkdir /tmp/host-mount
mount /dev/sda1 /tmp/host-mount # Host-Festplatte mounten!
chroot /tmp/host-mount # Host-Filesystem als Root
# → Vollständiger Host-Zugriff!
Oder:
# cgroup v1 release_agent:
mkdir /tmp/cgrp && mount -t cgroup -o memory cgroup /tmp/cgrp
echo 1 > /tmp/cgrp/notify_on_release
echo "$path/cmd" > /tmp/cgrp/release_agent
sh -c "echo ... > /tmp/cgrp/x/cgroup.procs"
# → Command wird mit Host-Rechten ausgeführt!
Vektor 2 - Docker Socket Mounted (/var/run/docker.sock):
Häufig in CI/CD-Pipelines zu sehen:
docker run -v /var/run/docker.sock:/var/run/docker.sock image
Escape:
# Von innen im Container:
docker run --rm -v /:/host alpine chroot /host /bin/bash
# Oder:
curl -X POST --unix-socket /var/run/docker.sock \
'http://localhost/containers/create' \
-d '{"Image":"alpine","HostConfig":{"Binds":["/:/host"],"Privileged":true}}'
# → Neuer Container mit Host-Root → Escape!
Warum: Docker-Socket = Root-Zugriff auf Docker-Daemon!
Wenn Angreifer Socket erreicht = vollständige Host-Kontrolle
Vektor 3 - Sensitive Volume Mounts:
Häufige gefährliche Mounts:
-v /etc:/etc → Host-etc editierbar!
-v /proc:/proc → Host-proc zugänglich!
-v ~/.ssh:/root/.ssh → SSH-Keys exponiert!
-v /home:/home → User-Home-Verzeichnisse lesbar
Exploitation:
Mount /etc: → /etc/crontab editieren → cron als root → RCE on Host
Mount /proc: → /proc/sysrq-trigger → Kernel-Crash
Mount /sys: → sysfs → Hardware-Manipulation
Vektor 4 - Kernel-Exploits (direkter Angriff):
Container und Host teilen denselben Kernel:
→ Kernel-CVE im Host → Exploit von Container aus möglich!
Bekannte CVEs:
CVE-2022-0492 (cgroup escape, Linux Kernel 5.x)
CVE-2019-5736 (runc Overwrite, betraf Docker < 18.09.2)
CVE-2019-16884 (AppArmor bypass in runc)
CVE-2020-15257 (containerd shim escape)
runc CVE-2019-5736:
→ Angreifer-Container mit spezieller Binary
→ Bei Ausführung von docker exec: runc-Binary auf Host überschrieben
→ Nächstes docker run: kompromittiertes runc → Host-RCE!
Vektor 5 - Capabilities-Missbrauch:
Gefährliche Capabilities (die Container manchmal haben):
CAP_SYS_ADMIN: wie --privileged, sehr weitreichend
CAP_NET_ADMIN: Netzwerkinterfaces manipulieren
CAP_SYS_PTRACE: Andere Prozesse debuggen (inkl. Host-Prozesse!)
CAP_NET_RAW: Raw Sockets → ARP-Spoofing, Sniffing
SYS_PTRACE exploit:
# Container hat CAP_SYS_PTRACE:
# PID 1 im Container ist Host-Prozess sichtbar (ohne PID-Namespace-Isolation)
# ptrace auf Host-PID → Shellcode in Host-Prozess injizieren
Vektor 6 - Kubernetes Specifics:
Service Account Credentials (zu weit):
cat /var/run/secrets/kubernetes.io/serviceaccount/token
→ Default Service Account in vielen K8s-Clustern zu mächtig!
→ kubectl mit Token: andere Pods, Secrets, ClusterRoleBindings?
Über-privilegierter Service Account:
kubectl auth can-i create pods -n kube-system
→ Wenn ja: Pod mit hostPath:/,privileged=true → Escape!
ETCD direkt erreichbar:
→ etcd-Port 2379 von Pod erreichbar?
→ Alle Kubernetes-Secrets im Klartext lesbar!
Erkennungsstrategien
Container-Escape erkennen:
Falcosecurity/Falco (Open Source):
→ Kernel-Level-Monitoring via eBPF
→ Erkennt: sensitives Mount, /proc-Zugriff, Syscall-Anomalien
Wichtige Falco-Rules:
- rule: Container mit privilegiertem Modus gestartet
condition: spawned_process and container and proc.name=docker and
container.privileged=true
priority: WARNING
- rule: Zugriff auf sensible Dateien im Container
condition: open_read and container and
fd.name in (/etc/shadow, /etc/passwd, /root/.ssh/id_rsa)
priority: CRITICAL
- rule: Docker-Socket-Zugriff im Container
condition: open_write and container and
fd.name=/var/run/docker.sock
priority: CRITICAL
Systemaudit (auditd):
-w /var/run/docker.sock -p rw -k docker-socket
-w /proc/sysrq-trigger -p w -k kernel-trigger
→ Log bei Write-Zugriff auf Docker-Socket / sysrq-trigger
Kubernetes Audit Logging:
→ Pod-Kreation mit hostPath / privileged=true → Alert!
→ Service-Account mit cluster-admin aus User-Namespace → Alert!
→ kubectl exec auf privilegierte Pods → Alert!
Schutzmaßnahmen
Container-Hardening:
1. Keine privilegierten Container (--privileged verboten!):
docker run --security-opt no-new-privileges nginx
→ Kein Privilege Escalation im Container
Kubernetes:
securityContext:
allowPrivilegeEscalation: false
privileged: false
capabilities:
drop: ["ALL"] # Alle Capabilities entfernen!
2. Read-Only Root Filesystem:
docker run --read-only nginx
Kubernetes:
securityContext:
readOnlyRootFilesystem: true
→ Malware kann keine Executables schreiben!
3. Nicht als root laufen:
Dockerfile: USER 1000
Kubernetes:
securityContext:
runAsNonRoot: true
runAsUser: 1000
4. Seccomp-Profile (System-Call-Filtering):
docker run --security-opt seccomp:profile.json nginx
Kubernetes:
securityContext:
seccompProfile:
type: RuntimeDefault
→ Nur erlaubte Syscalls → Kernel-Exploit-Fläche reduziert
5. AppArmor-Profile:
docker run --security-opt apparmor:docker-default nginx
→ MAC-Regeln zusätzlich zu Capabilities
6. Keine gefährlichen Volume-Mounts:
□ Kein /var/run/docker.sock
□ Kein /proc, /sys, /dev
□ Kein /, /etc, /home
□ hostPath: möglichst vermeiden, wenn nötig: readOnly: true
7. Kubernetes-spezifisch:
□ Pod Security Admission (PSA): enforce Restricted-Profil
□ Network Policies: Pods dürfen nur kommunizieren was nötig
□ Service Account: eigene SA pro Deployment, minimale Rechte
□ automountServiceAccountToken: false wenn nicht nötig
□ ETCD: nur über API-Server erreichbar, kein direkter Pod-Zugriff