Broken Access Control on Docker
How Broken Access Control Manifests in Docker
Broken Access Control in Docker environments often stems from misconfigured permissions and exposed administrative interfaces. Docker's architecture creates unique attack surfaces that differ from traditional web applications. When Docker daemons are exposed without authentication, attackers can execute arbitrary commands on the host system, effectively bypassing all application-level security controls.
The most critical vulnerability occurs when Docker's API socket is exposed over the network without proper authentication. By default, Docker listens on a Unix socket, but many deployments mistakenly bind to TCP ports like 2375 (unencrypted) or 2376 (TLS). An exposed Docker daemon allows attackers to mount the host filesystem, escape container isolation, and execute commands as root on the underlying system.
# Vulnerable Docker daemon configuration
dockerd -H tcp://0.0.0.0:2375This configuration is equivalent to giving an attacker root access to your entire infrastructure. Once connected, an attacker can mount the root filesystem and modify critical system files:
# Mount host root filesystem into container
docker run -it --rm -v /:/host alpine chroot /host /bin/shAnother common Docker-specific access control issue involves container image permissions. When building Docker images, developers often copy files with overly permissive ownership or create containers that run as root. This allows processes inside containers to modify files they shouldn't be able to access, leading to privilege escalation.
# Vulnerable Dockerfile - runs as root
FROM node:14
WORKDIR /app
COPY . .
RUN npm install
USER root # Dangerous - runs container as root
CMD ["node", "server.js"]Docker's networking features also introduce access control problems. Docker networks created with the default bridge driver expose services to all containers on the same host unless explicitly isolated. Without proper network segmentation, a compromised container can access internal services of other containers, leading to lateral movement within the Docker environment.
Docker-Specific Detection
Detecting Broken Access Control in Docker environments requires both configuration analysis and runtime scanning. The first step is auditing Docker daemon configurations to ensure API sockets aren't exposed over unencrypted networks. Check for Docker processes listening on TCP ports without TLS:
# Check for exposed Docker daemon
ss -tlnp | grep dockerContainer image analysis reveals permission issues that could lead to access control violations. Scanning Docker images for files with world-writable permissions or setuid binaries helps identify potential privilege escalation vectors:
# Scan image for dangerous permissions
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock docker/dockerfile:1.5-lint docker run --rm -v /:/mnt alpine find /mnt -type f -perm /6000Network segmentation analysis is critical for Docker access control. Use Docker's built-in commands to audit network configurations and identify containers that can communicate without restrictions:
# List all Docker networks and attached containers
docker network ls
docker network inspect <network_id>middleBrick provides specialized Docker API scanning that tests the unauthenticated attack surface of Docker endpoints. The scanner attempts to connect to exposed Docker APIs and evaluates the risk of unauthorized access. For containerized applications, middleBrick analyzes API endpoints running inside containers to detect broken access control patterns specific to the Docker runtime environment.
The scanner checks for common Docker misconfigurations including exposed Docker sockets, containers running as root, and overly permissive file permissions within images. middleBrick's Docker-specific checks include testing for container escape vectors and privilege escalation opportunities that only exist in containerized environments.
Docker-Specific Remediation
Remediating Broken Access Control in Docker environments requires a defense-in-depth approach. Start by securing the Docker daemon itself. Always bind Docker to a Unix socket or use TLS encryption when exposing the API over TCP:
# Secure Docker daemon configuration
dockerd -H unix:///var/run/docker.sock --tlsverify --tlscacert=/etc/docker/ca.pem --tlscert=/etc/docker/server-cert.pem --tlskey=/etc/docker/server-key.pemFor container images, follow the principle of least privilege. Never run containers as root unless absolutely necessary. Use non-privileged users and set proper file ownership during the build process:
# Secure Dockerfile
FROM node:14
WORKDIR /app
COPY --chown=node:node . .
RUN npm install --unsafe-perm=false
USER node # Run as non-root user
CMD ["node", "server.js"]Implement proper network segmentation using Docker networks with explicit access controls. Create separate networks for different application tiers and only connect containers that need to communicate:
# Create isolated networks
docker network create --driver bridge frontend
docker network create --driver bridge backend
docker network create --driver bridge databaseControl container capabilities to prevent privilege escalation. Drop unnecessary Linux capabilities and use read-only filesystems where possible:
# Run container with restricted capabilities
docker run --cap-drop ALL --cap-add CHOWN --read-only myappImplement Docker Content Trust to ensure only trusted images can be pulled and run. This prevents attackers from replacing legitimate images with malicious ones that contain backdoors or privilege escalation code:
# Enable Docker Content Trust
export DOCKER_CONTENT_TRUST=1For production environments, use Docker's user namespace remapping to provide additional isolation between containers and the host system. This feature maps container root users to non-privileged users on the host:
# Configure user namespace remapping
echo "{"userns-remap": "default"}" > /etc/docker/daemon.jsonRegular security scanning of Docker images and containers using tools like middleBrick helps maintain access control integrity. The scanner can detect when containers are running with excessive privileges or when Docker configurations drift from secure baselines.
Frequently Asked Questions
How can I test if my Docker daemon is exposed to the network?
Use ss -tlnp | grep docker to check for Docker processes listening on TCP ports. If you see Docker listening on 2375 or 2376 without TLS, your daemon is exposed. You can also try connecting with curl http://localhost:2375/version - if this returns Docker version information, the API is accessible.
What's the difference between running containers as root vs non-root in Docker?
Running containers as root means processes inside have UID 0, which can modify any file and potentially escape the container through kernel vulnerabilities. Running as non-root (using USER directive) limits the damage an attacker can do if they compromise the container, as they'll have limited system privileges. Non-root containers are significantly more secure and should be the default practice.