Docker API Container Escape
Unauthenticated Docker API access enables launching a new container with the host filesystem mounted inside it. Since the Docker daemon runs as root, the new container has full read-write access to every file on the host. Combining this with nsenter — a tool for entering Linux namespaces — produces a root shell on the host system outside any container boundary. This is the primary exploitation path for exposed Docker API and consistently appears on HTB machines and real-world engagements. Confirm unauthenticated access through unauthenticated access assessment first.
Method 1 — Mount Host Filesystem and Read Sensitive Files
Start a container with the host root filesystem mounted at /host. Use any image already present on the target to avoid a slow pull:
nginx:latest mysql:8.0 ubuntu:22.04
root@a1b2c3d4e5f6:/#
The chroot /host makes the container session behave as if it is running directly on the host filesystem. You now have a root shell on the host. Read /etc/shadow, SSH keys, and any other sensitive files:
root:$6$abc123$hashedpassword:19000:0:99999:7:::
-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXk...
Method 2 — Get a Reverse Shell on the Host with nsenter
nsenter enters the PID 1 namespace on the host — stepping fully outside any container isolation:
--pid=host shares the host PID namespace with the container. nsenter -t 1 enters all namespaces of PID 1 (the host init process). The resulting shell is running on the host with full root privileges, not inside any container.
Method 3 — Write SSH Key to Host
Plant an SSH public key in root's authorized_keys for persistent access without a reverse shell:
root@docker-host-01:~#
Important
Remove any planted SSH keys before engagement close. Document the exact key fingerprint and the path it was written to. Planted keys persist until explicitly removed.
Method 4 — Via the REST API Without the Docker CLI
When the docker CLI is not available on the attack machine, perform the same attack using raw API calls:
"Id": "c1d2e3f4a5b6..."
root:$6$abc123$hashedpassword:19000:0:99999:7:::
References
-
Docker Engine APIdocs.docker.com/engine/api (opens in new tab)
Container create, start, and logs API reference
-
nsenter(1) manualman7.org/linux/man-pages/man1/nsenter.1.html (opens in new tab)
Namespace entry — pid, mount, uts, ipc, net options
Was this helpful?
Your feedback helps improve this page.