Container Security

A Dirty Cow Container Exploit Persists

By Andson Tung

DIrty Cow ExploitWe have seen a lot of reports on how the Linux kernel can be compromised by the Dirty Cow (CVE-2016-5195) exploit. One technique that attackers use is to exploit this kernel bug to overwrite a so-called setuid program in the system. A setuid program allows the user to temporarily elevate the privilege in order to perform a certain task. By replacing the setuid program, the attacker can gain root access privilege when the program is executed, and be able to do whatever he/she wants.

You may think that the damage can be cleaned up if the compromised container is stopped and removed. However, that is not the case! In this demo of a Dirty Cow container exploit we will show that it has a long lasting effect on the container host, beyond the lifecycle of the compromised container. In fact, container immutability is broken.

‘passwd’ in a Linux system is one of these setuid programs. We will use it as an example in this demo.

Let’s do this step by step to see how the file changes.

Step 1 – Start a clean ubuntu:14.04 container

In the beginning, we have a clean ubuntu 14.04 running on a host and then start a clean ubuntu:14.04 container.

docker run -ti --rm -v /path/dirtycow:/tmp/case ubuntu:14.04 bash

Let’s record the hash of /usr/bin/passwd file in ubuntu:14.04 container as shown below.

044e63fc4a13bd08fba6fb457f36c2f7  /usr/bin/passwd

Let’s also record the hash of following files in the docker unification file system located on host node after the ubuntu:14.04 container is started.

044e63fc4a13bd08fba6fb457f36c2f7  /var/lib/docker/aufs/diff/1a84e3b38dc86d47c70e584051863b5547e205773d7e64dede837de559573710/usr/bin/passwd
044e63fc4a13bd08fba6fb457f36c2f7  /var/lib/docker/aufs/mnt/e2d3c4694e8d2089bc47125a2a6a9b74675dc8020b5b10a561a0e2da113b6b34/usr/bin/passwd

Step 2 – Stop and remove an ubuntu:14.04 container

The directory below will be removed after the ubuntu:14.04 container is stopped and removed.

/var/lib/docker/aufs/mnt/e2d3c4694e8d2089bc47125a2a6a9b74675dc8020b5b10a561a0e2da113b6b34

The previous diff directory still stays on host node for the ubuntu:14.04 image.

044e63fc4a13bd08fba6fb457f36c2f7 /var/lib/docker/aufs/diff/1a84e3b38dc86d47c70e584051863b5547e205773d7e64dede837de559573710/usr/bin/passwd (stay in the system)

Step 3 – Start a clean ubuntu:14.04 container again using the same docker command as Step 1

When a new clean ubuntu:14.04 container is started, the new mnt directory will be created on the host.

044e63fc4a13bd08fba6fb457f36c2f7  /var/lib/docker/aufs/diff/1a84e3b38dc86d47c70e584051863b5547e205773d7e64dede837de559573710/usr/bin/passwd (reuse)
044e63fc4a13bd08fba6fb457f36c2f7  /var/lib/docker/aufs/mnt/4f92c046bc94d42e28f772a150ec6d5ec663154e32a75d14f87bae87b564b8ed/usr/bin/passwd (new created)

Step 4 – Run passwd before the system is compromised

As seen in the following, the user is promoted to enter the password.

Step 5 – Execute a dirty cow exploit with non-root user in the ubuntu:14.04 container

After the Dirty Cow container exploit is executed in the ubuntu:14.04 container, the md5 hash for passwd on the host node is changed for both diff and mnt directories.

62152cbd766001ae450a2b48c7f72d99  /var/lib/docker/aufs/diff/1a84e3b38dc86d47c70e584051863b5547e205773d7e64dede837de559573710/usr/bin/passwd (version 1)
62152cbd766001ae450a2b48c7f72d99  /var/lib/docker/aufs/mnt/4f92c046bc94d42e28f772a150ec6d5ec663154e32a75d14f87bae87b564b8ed/usr/bin/passwd

And of course, it also changes on /usr/bin/passwd in the container as well.

62152cbd766001ae450a2b48c7f72d99  /usr/bin/passwd

Step 6 – Copy the original passwd back to /usr/bin/passwd in the ubuntu:14.04 container

A new version of passwd on the host will be created.

044e63fc4a13bd08fba6fb457f36c2f7  /var/lib/docker/aufs/diff/4f92c046bc94d42e28f772a150ec6d5ec663154e32a75d14f87bae87b564b8ed/usr/bin/passwd (version 2)
62152cbd766001ae450a2b48c7f72d99  /var/lib/docker/aufs/diff/1a84e3b38dc86d47c70e584051863b5547e205773d7e64dede837de559573710/usr/bin/passwd (version 1)
044e63fc4a13bd08fba6fb457f36c2f7  /var/lib/docker/aufs/mnt/4f92c046bc94d42e28f772a150ec6d5ec663154e32a75d14f87bae87b564b8ed/usr/bin/passwd (current state)

Step 7 – Stop and remove an ubuntu:14.04 container

The mnt directory and diff directory with version 2 will be removed after the ubuntu:14.04 container is stopped and removed. The previous diff directory still stays on the host node for the ubuntu:14.04 image.

As you can see, the original file in the ubuntu:14.04 image is compromised now.

62152cbd766001ae450a2b48c7f72d99  /var/lib/docker/aufs/diff/1a84e3b38dc86d47c70e584051863b5547e205773d7e64dede837de559573710/usr/bin/passwd

Step 8 – Start an ubuntu:14.04 container again

Use the docker command again as in Step 1. When a new ubuntu:14.04 container is started, the new mnt directory will be created on the host.

62152cbd766001ae450a2b48c7f72d99  /var/lib/docker/aufs/diff/1a84e3b38dc86d47c70e584051863b5547e205773d7e64dede837de559573710/usr/bin/passwd (reuse)
62152cbd766001ae450a2b48c7f72d99  /var/lib/docker/aufs/mnt/e595ebc3fe0b08abf46caf1a0a0bdfc08b2a3e822e91a9699d69c87513fcdf7d/usr/bin/passwd (new created)

Now you can see that the /usr/bin/passwd in the container is compromised already.

62152cbd766001ae450a2b48c7f72d99  /usr/bin/passwd

Step 9 – Run passwd with a non-root user after the system is compromised

You can see below that the password dialog is gone. Instead, the process gains root access permission now.

No matter how many times you keep starting, stopping and removing the container, the system will remain compromised with the Dirty Cow container exploit until the entire ubuntu:14.04 image is removed.

Detection and Prevention

NeuVector is a comprehensive run-time security solution for containers and their hosts. A hacking attack is often compromised of several steps in the chain, and NeuVector is able to detect the compromise at several points.

First, NeuVector scans hosts and containers for vulnerabilities, and would identify that the Dirty Cow vulnerability existed. Second NeuVector can detect when a compromised host or container process suffers from a privilege escalation to root (Step 5). Third, when a compromised container process attempts to break out and connect to another container, NeuVector violation detection would determine that this connection was suspicious unauthorized traffic. These connection could generate alerts and blocked if desired.

About the Author

Andson Tung is on the Technical Staff at NeuVector.

About the Author

NeuVector delivers an application-aware container network security solution. The NeuVector containers deploy easily in minutes and discover running services and applications. A security policy is automatically created and updated when containers launch, scale up or scale down. NeuVector detects container threats, violations, and vulnerabilities.