HIGH security misconfigurationdocker

Security Misconfiguration on Docker

How Security Misconfiguration Manifests in Docker

Security misconfiguration in Docker often appears when the daemon, containers, or images are deployed with defaults that expose unnecessary privileges or access paths. A common pattern is exposing the Docker Engine API over TCP without TLS or authentication. When the daemon is started with -H tcp://0.0.0.0:2375 (or the equivalent --host tcp://0.0.0.0:2375 flag), anyone who can reach the port can issue Docker commands such as docker ps, docker run, or docker exec without any credentials. This has been exploited in the wild, for example in CVE‑2020-15257 where an unauthenticated API allowed attackers to run privileged containers and gain host root.

Another frequent misconfiguration is mounting the host’s Docker socket inside a container (-v /var/run/docker.sock:/var/run/docker.sock). While useful for CI pipelines, it gives the container full control over the host Docker daemon. If the container is compromised, an attacker can spawn new containers with --privileged, mount host directories, or execute arbitrary code on the host. This pattern has been linked to incidents such as the TeslaCrypt ransomware campaign that abused exposed Docker sockets to deploy mining containers.

Privileged containers (--privileged) or containers launched with excessive Linux capabilities (e.g., --cap-add=SYS_ADMIN) also constitute a misconfiguration. They bypass namespace isolation and can modify host kernel modules, access hardware devices, or reconfigure network settings. Attackers chain this with volume mounts to read sensitive files like /etc/shadow or /var/lib/docker/overlay2/.../init. The OWASP API Top 10 classifies these issues under M9 – Security Misconfiguration, and they are regularly observed in container‑native environments where developers prioritize convenience over least‑privilege principles.

Docker-Specific Detection

Detecting Docker misconfigurations starts with enumerating the attack surface that a black‑box scanner can reach. The Docker Engine API exposes several unauthenticated endpoints when TLS is disabled, such as:

  • GET /containers/json – lists running containers
  • GET /images/json – lists images
  • POST /containers/create – creates a new container
  • GET /_ping – daemon health check

If any of these endpoints return a successful HTTP 200 response without requiring authentication tokens or client certificates, the daemon is likely misconfigured. MiddleBrick’s unauthenticated, black‑box scan will automatically probe the supplied base URL for these paths. For example, running the CLI against a host that exposes the Docker daemon yields a finding such as:

$ middlebrick scan http://example.com:2375/containers/json
{
  "score": 32,
  "grade": "F",
  "findings": [
    {
      "id": "DOCKER-EXPOSED-API",
      "severity": "high",
      "description": "Docker Engine API accessible without authentication or TLS.",
      "remediation": "Secure the daemon with TLS and restrict network access, or bind to a Unix socket only."
    }
  ]
}

Beyond the API, middleBrick can detect exposed Docker sockets indirectly by scanning for HTTP services that forward to the socket (e.g., a sidecar that exposes /docker endpoints). The scanner also checks for common misconfigurations in container images, such as running as root (USER root in Dockerfile) or using the latest tag, which can be inferred from image metadata returned by the registry endpoints.

Because the scan is agentless and requires only a URL, teams can integrate it into CI pipelines. Adding the middleBrick GitHub Action to a workflow will fail the build if the security score drops below a defined threshold, preventing the deployment of images or services that exhibit Docker‑specific misconfigurations.

Docker-Specific Remediation

Remediation focuses on applying Docker’s native security features to enforce least privilege and reduce the attack surface.

Secure the Docker daemon: If remote API access is required, bind the daemon to a TCP port only with TLS mutual authentication. Create a certificate authority, generate server and client certificates, and start the daemon with:

dockerd \
  --host=tcp://0.0.0.0:2376 \
  --tlsverify \
  --tlscacert=/etc/docker/ca.pem \
  --tlscert=/etc/docker/server-cert.pem \
  --tlskey=/etc/docker/server-key.pem

Then restrict firewall rules to allow only trusted IPs to reach port 2376.

Avoid mounting the Docker socket: Unless absolutely necessary, do not bind‑mount /var/run/docker.sock into containers. If a CI job needs to control Docker, use a dedicated Docker-in-Docker (DinD) service that runs as a separate container with its own isolated daemon, or use the docker CLI against a remote daemon that is properly authenticated.

Drop privileges and capabilities: Run containers as a non‑root user by specifying a USER directive in the Dockerfile. For example:

FROM node:20-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY . .
RUN npm ci
USER appuser
CMD ["node", "index.js"]

Additionally, drop all unnecessary Linux capabilities and add only those required:

docker run --rm \
  --cap-drop ALL \
  --cap-add=NET_BIND_SERVICE \
  --user appuser \
  myimage:1.0.0

Use read‑only root filesystem and limit resources:

docker run --read-only \
  --tmpfs /tmp \
  --memory=256m \
  --cpus=0.5 \
  myimage:1.0.0

Image hygiene: Base images should be scanned for vulnerabilities, avoid the latest tag, and pin to specific digests. Use multi‑stage builds to exclude build‑time tools from the final image.

By applying these Docker‑native controls, the attack surface shrinks significantly, and a subsequent middleBrick scan will reflect an improved security score, moving from an F toward higher grades as the misconfigurations are eliminated.

Frequently Asked Questions

How can I verify that my Docker daemon is not exposed without authentication?
Run a simple curl against the daemon’s API endpoint, for example curl -s http://:2375/containers/json. If you receive a JSON list of containers without providing any TLS client certificates or authentication headers, the daemon is exposed. middleBrick will flag this as a high‑severity finding during its unauthenticated scan.
What is the difference between a privileged container and a container with added capabilities?
A privileged container (--privileged) disables most isolation mechanisms, giving the container nearly full access to host devices and kernel interfaces. Adding individual capabilities (--cap-add) grants only specific Linux privileges (e.g., NET_ADMIN for network configuration) while keeping other namespaces intact. Both represent misconfigurations if the granted privileges exceed what the application actually needs.