Earlier today (11 Feb 2019), a new vulnerability in runc was announced. This vulnerability allows container escape simply by running a malicious image. When the malicious image is run, it exploits a defect to then overwrite the runc binary on the host, thereby allowing unlimited control of both the host itself and any other containers running on it. The vulnerability affects LXC as well and the LXC patch includes a good description of the underlying mechanics of the attack:
“The attack can be made when attaching to a running container or when starting a
container running a specially crafted image. For example, when runC attaches
to a container the attacker can trick it into executing itself. This could be
done by replacing the target binary inside the container with a custom binary
pointing back at the runC binary itself. As an example, if the target binary
was /bin/bash, this could be replaced with an executable script specifying the
interpreter path #!/proc/self/exe (/proc/self/exe is a symbolic link created
by the kernel for every process which points to the binary that was executed
for that process). As such when /bin/bash is executed inside the container,
instead the target of /proc/self/exe will be executed – which will point to the
runc binary on the host. The attacker can then proceed to write to the target
of /proc/self/exe to try and overwrite the runC binary on the host. However in
general, this will not succeed as the kernel will not permit it to be
overwritten whilst runC is executing. To overcome this, the attacker can
instead open a file descriptor to /proc/self/exe using the O_PATH flag and then
proceed to reopen the binary as O_WRONLY through /proc/self/fd/
write to it in a busy loop from a separate process. Ultimately it will succeed
when the runC binary exits. After this the runC binary is compromised and can
be used to attack other containers or the host itself.”
The CVE has a high CVSS rating (7.2) and exploit code is scheduled to be published for it in a week (18 Feb). Thus, it’s important to act quickly to patch it, as there’s a significant likelihood of the expolit code being weaponized soon after. See the links section below for more information on available updates from common vendors and cloud platforms, some of whom have already issued updates and / or patched their platforms.
How Twistlock protects
While you should always update vulnerable components, particularly critical parts of your infrastructure stack like runc, Twistlock offers several layers of defense in depth that help mitigate the problem.
Layer 1: Know if you’re vulnerable (Binary level vulnerability detection)
There are many ways to install a container runtime, from an item in your operating system’s package manager, to a vendor’s standalone installer, to just ‘curl pipe to bash’ from Docker’s website. While many tools can detect vulnerable packages, Twistlock goes further and detects vulnerabilities within many common binaries themselves, including Docker. This means that no matter how you’ve installed Docker and no matter whether that source has published vulnerability data, we’re already detecting and showing you what’s vulnerable.
Layer 2: Don’t run malicious images (Trusted Images)
A key aspect of this attack is running a malicious image in the first place. The attack cannot be performed simply by having network access to a container host. Thus, one of the most effective mitigations is provided by Twistlock’s Trusted Images feature. Trusted Images is a feature we introduced almost 2 years ago in Twistlock 1.7 that enables you to centrally specify sets of registries, repositories, images, and even base layers that are considered ‘trusted’ within your organization.
Once this list is established, Twistlock can then be used to enforce that only these trusted images are allowed to run within your environment and that all other images are automatically blocked.
Layer 3: Prevent running containers that can be exploited (Compliance checks)
Twistlock has a wide and deep compliance feature set covering literally hundreds of individual checks from the Linux, Docker, and Kubernetes CIS benchmarks (as well as extensible custom checks). Two CIS checks in particular are effective mitigations for this vulnerability.
First, is preventing containers that share hosts’ user namespaces. This is covered in recommendation 5.30, Ensure the host’s user namespaces is not shared (Scored), in the Docker CIS benchmark. When Twistlock is configured to block containers configured to share the host user namespace, this exploit is ineffective.
Another related check is to ensure that containers cannot be run as root. This check effectively prevents the second stage of the exploit – overwriting the runc binary – since it’s normally owned by root.
Both compliance checks should be used together to mitigate the problem and are recommended as important security controls to enforce in general.
The National Vulnerability Database entry isn’t yet published at the time of writing, but the URL it will be published to is: https://nvd.nist.gov/vuln/detail/CVE-2019-5736
Docker 18.09.2 release notes: https://docs.docker.com/engine/release-notes/
Red Hat CVE database entry: https://access.redhat.com/security/cve/cve-2019-5736
Red Hat vulnerability response: https://access.redhat.com/security/vulnerabilities/runcescape
AWS security bulletin: https://aws.amazon.com/security/security-bulletins/AWS-2019-002/
Google Cloud Platform: https://cloud.google.com/kubernetes-engine/docs/security-bulletins
Watch the CNSP podcast on the RunC and Docker vulnerability discovered yesterday: CVE-2019-5736.
Follow us on Twitter
Follow us on Twitter for real time updates on the cloud native ecosystem, Twistlock product, and cloud native security threats.