Exposed Docker Daemon
A Docker daemon answering on the network without TLS is remote root on the host. Take a machine through the exposed API, then lock it down with TLS, client certificates, and a scoped socket proxy.
What Is Exposed Docker Daemon?
The Docker API is root-equivalent and ships with no authentication. A daemon bound to a network port without TLS lets anyone who can reach it start containers, mount the host, and read anything on the machine. Mounting the daemon socket into a container hands that container the same power. This exercise covers both: watch an attacker take a host through an exposed daemon, then lock it down with TLS, client certificates, and a scoped socket proxy.
What You'll Learn in Exposed Docker Daemon
- Anyone who can reach the API can start a container that mounts the host filesystem, which gives full read and write access to the machine.
- No. The socket is the same root-equivalent API, so any compromise of that container becomes compromise of the host.
- TLS with mutual client-certificate authentication, or a scoped proxy that only permits the specific API calls the caller needs.
- That attack needs code execution inside a container first. This one is remote and unauthenticated, so the attacker needs no foothold at all.
Exposed Docker Daemon — Training Steps
-
Reading the public status page
Bob is not inside anything. He is on his own laptop, reading Palliston's public operations page. It is meant to reassure customers that the platform is healthy, and in doing so it names the production nodes, their public IPs, and the Docker engine each one runs. Take a look at what it exposes before Bob puts it to use.
-
The line that says too much
It only takes one line. A production node's public IP and the fact that it runs Docker are all Bob needs to try the cheapest attack there is.
-
Knock on the daemon
The Docker daemon can be told to listen on a network port instead of only the local socket. When it is, and TLS is off, it answers anyone. Bob points his own Docker CLI at that node's port 2375 and asks it the most harmless question there is: what version are you. If it answers, the game is already over.
-
Read the production fleet
The Docker API is not a narrow thing. It lists, starts, stops, and builds containers, and it does all of it as root. Bob's first move with it is simply to look: what is this host actually running.
-
Mount the host, take the secrets
Bob does not need to break into the running containers. The daemon will start a brand new one for him, and it will mount whatever he asks it to. He asks for the host's entire root filesystem at /host, then reads the production environment file straight through the mount. The container is his. The host is under it. There was never a wall between them.
-
What made this possible
One beat on the mechanism before the response begins.
-
The daemon logs a stranger
Palliston ships its Docker daemon logs to a central collector. It does not take an intrusion-detection product to notice what turned up: API calls to the daemon on ops-node-01, from an IP that belongs to no one at Palliston.
-
Confirm the door is open
Before changing anything, Alice reproduces what the logs describe. If an unauthenticated version probe from her own machine answers, the daemon is exposed exactly as Priya feared.
-
Open the daemon config
The daemon's behaviour is set in one file, /etc/docker/daemon.json. Whatever told it to listen on the network without TLS is a line in here.
-
Find what opened the port
Two settings, side by side, are the entire exposure. One puts the API on the network; the other tells it not to check who is calling.