Skip to main content

Am I in a Container?

Enumeration

Capabilities determine what the container is allowed to do. A long list or cap_sys_admin means you have serious power.
Privileged containers have all capabilities, seccomp disabled, and full access to host devices.
Docker’s default bridge puts containers on 172.17.0.0/16. User-defined bridges (from docker-compose or docker network create) get their own subnet: 172.18.0.0/16, 172.19.0.0/16, and so on. The .1 address of each subnet is the Docker host. Other containers are often reachable here.
Mounted volumes, bind mounts, and Docker secrets are common paths to host access or credentials.

Breakout Scenarios

Being in the docker group is effectively root. Mount the host filesystem into a container and chroot in.
Alternative: create a SUID bash binary via the mounted filesystem, then execute it on the host.
If /var/run/docker.sock is writable, you can talk to the daemon directly without being in the docker group.
Privileged containers have all capabilities and can see host block devices. Mount the host drive and write to it directly.
A non-privileged container with CAP_SYS_ADMIN and no AppArmor profile can abuse cgroup release agents to execute commands on the host.
Catch the shell on the attacker:
If sudo -l shows (root) NOPASSWD: /usr/bin/docker exec *, you can exec into any running container as root.

Windows Containers

Docker can run Windows containers, and labs often place one on a non-default bridge such as 172.19.0.0/16. From a shell on the Linux host, 172.19.0.1 is the Docker host itself (the gateway) and the Windows container is usually the next address, 172.19.0.2. It typically exposes SMB (445) and RDP (3389) on the bridge but nothing to the outside.

Reaching It From Your Attacker Box

172.19.0.0/16 is only routable from the Linux host, so pivot through it. See Ligolo, Chisel, Proxychains.

xfreerdp

xfreerdp3 is the v3 binary; older systems use xfreerdp. /cert:ignore is almost always needed against a container’s self-signed cert.
Through a SOCKS tunnel, RDP is fragile: add /timeout:20000, and if NLA fails during negotiation fall back to /sec:tls. A direct Ligolo route is far more stable than proxychains for interactive sessions.

Enabling RDP If It’s Not Listening

If 3389 is closed on the container but you have SMB admin: