Docker
Built-in
One of the first vulnerabilities you need to address is the built-in Linux Capabilities in the Kernel. By default, Docker enables a "limited" set of capabilities in the Linux Kernel when running containers. These capabilities can still be abused to exit the Operating System container. Some of them are non-standard ones like SYS_ADMIN that can be used to break out of containers. Look at this example below from trailofbits.com.
So, what is occurring here? Using the SYS_ADMIN capability in a container, you can look at cgroups, specifically Cgroupsv1. Cgroups in that version can have parent/child relationships in which a child set of cgroups can survive outside of the parent. In this example, the attacker is using the release_agent, which will execute commands when a cgroup terminates. If you can tell the system to execute commands when the cgroup exists, you can run those commands on the host. So, in this example, if you have SYS_ADMIN capabilities, you can find a simple escape path.
Docker.sock
In Linux everything is denoted as a file. Objects like devices, sockets, and the like are all files. Socket files are network sockets that can be used to interact with system daemons and network connections. When the docker CLI command interacts with a running process, it runs its own system daemon. You can choose to expose docker in a network port, but by default, those ports are insecure; you only need to interact with the docker API to run docker commands. You may, however, find that the "docker.sock" is in a container. Why would such a thing be required? If you are running a container that requires interaction with the host's own API, then you will need to place the "docker.sock" file in the container. Many systems do this. Some systems programmatically create configuration files based on the containers that exist on the host. Other systems will manage the containers on the host or monitor them. If you use a CI/CD system like that of Jenkins, at times, you may want to emit a build artifact of a container. If you are running Jenkins itself within a container, then you would be implementing what is called "Docker In Docker".
You have now found a Docker.sock file. How can you abuse it? We must remember that Docker.sock is what the Docker CLI and other tools will programmatically use to interact with the Docker host. One option is to do just that and interact with the Docker host system. Given that we may not realistically be root or bring over tools onto a container, what else could we do?
Curl gives us the capability to interact with these types of files. How so? We can first specify the unix- socket flag, pointing the curl binary to a unix socket to interact with the host. Interacting with the socket only changes our transport mechanism, and we still need URLs to pass. In this case, with the default docker.sock file, we can interact with the host by specifying docker cli commands such as:
This command will interact with the docker socket and send over that socket interface an API call to GET http://localhost/images/json. This would be the docker CLI command to docker get images. Using this instruction set, we can run anything we want. Do you want to run a container that runs a backdoor and gives you full system access? That can be done given that Docker runs as a root daemon process.
Last updated