the_open_door
coffee
ESEN
← Back to index

Pivoting into Docker containers

After getting a shell on a Linux host, you often find that some services don't run on the host itself but inside Docker containers. Each container has an internal IP (on the default bridge network, the 172.17.0.0/16 range, with 172.17.0.1 being the host and 172.17.0.2, .3, ... the containers) and usually exposes ports that are not published outward. That internal network plane is fertile ground: apps without hardened authentication, old versions, backups.

Discover containers and ports. With no tools installed, plain bash is enough. A ping sweep finds live IPs in the bridge range:

for i in $(seq 1 255); do ping -c1 -W1 172.17.0.$i | grep "bytes from" & done

And a port sweep against an IP using bash's /dev/tcp pseudo-device (no nmap needed on the victim):

for p in $(seq 1 65535); do (echo > /dev/tcp/172.17.0.2/$p) 2>/dev/null && echo "open: $p"; done

Reach the service. The container port (e.g. 172.17.0.2:5000) isn't reachable from our attacking machine. Solve it with a port forward over SSH, so a local port of ours talks to the internal service:

ssh -L 5001:172.17.0.2:5000 user@target   # now 127.0.0.1:5001 -> container:5000

What to look for inside. Once you have a shell in the container (e.g. after an RCE in the app it hosts), the loot is usually in the app's /datastore or data directory: config files, exportable backups and credentials. Those secrets often get you back to the host via credential reuse (a su or SSH with the recovered password).

Caveat. Being root inside a container is not root on the host: the container is isolated unless misconfigured (sensitive mounts, --privileged, exposed Docker socket). The typical lab pivot isn't escaping the container but extracting credentials from it and reusing them against the host.

How to detect it. The signature is internal recon from an already-compromised host: a ping and port sweep against 172.17.0.0/16 generates hundreds of short-lived connections and ARP/ICMP to the bridge range in very little time (visible in netflow/conntrack or via auditd over connect calls), a pattern a normal service never produces. It's accompanied by an ssh -L tunnel from the host (an SSH session with unusual forwarding) and reads of container data directories (/datastore). Later reuse of a recovered credential leaves an anomalous su/login on the host.

Defence. Don't keep secrets in backups accessible inside the container; segment the bridge network; don't expose the Docker socket; keep containerized apps updated.

Toolsdocker

Machines where it's used