Skip to main content

"Dirty Pipe" Linux vulnerability and your containerized applications (CVE-2022-0847)

wordpress-sync/blog-feature-security-alert-purple

2022年3月9日

0 分で読めます

What is the “Dirty Pipe” vulnerability? (CVE-2022-0847)

Recently, CVE-2022-0847 was created detailing a flaw in the Linux kernel that can be exploited allowing any process to modify files regardless of their permission settings or ownership. The vulnerability has been named “Dirty Pipe” by the security community due to its similarity to “Dirty COW”, a privilege escalation vulnerability reported in CVE-2016-5195, and because the flaw exists in the kernel pipeline implementation. There are multiple references of this vulnerability documented in the Snyk Intel Vulnerability Database if you’d like to dive deeper.

In this article, we will discuss the risks your containerized workloads face and we will dive under the covers to see how the contents of container images and other, normally-read-only files can be modified by a bad actor regardless of their UID and file system permissions.

First off, let’s cover what you can do right now to protect your systems from Dirty Pipe.

TL;DR: Upgrade your Linux hosts

The only known fix for this vulnerability is to upgrade your Linux hosts to one of the following kernel versions:

  • 5.16.11

  • 5.15.25

  • 5.10.102

There are no other mitigation options that can protect your systems should a malicious actor get access to your environment.

How Dirty Pipe impacts your container images

Container images 101

wordpress-sync/blog-dirty-pipe-layers

A container image is basically made up of a collection of layers that are overlaid on each other. When a container is started, the runtime engine (Docker, containerD, cri-O, etc), merges these layers together and presents the resulting aggregate as the filesystem to the process. These layers are always read-only and any mutation is done in a read-write layer that is created specifically for each container instance using a copy-on-write (COW) pattern. This read-write layer is ephemeral as it is destroyed when the container is removed from the system. The read-write layer also can be omitted by starting the container in read-only mode, effectively making the container immutable.

It is common advice to make sure your containers run their processes as non-privileged users and to make their root file systems read-only. These steps make it much more difficult for a bad actor to leverage application vulnerabilities to expand their attack because it greatly complicates the ability to bring their own code or scripts into the container filesystem. Check out our container security guide for additional best practices.

Dirty Pipe exploited in a container

The details about how the Dirty Pipe vulnerability works are out of scope for this article — see the original discovery blog for all the gory details — but at a high level a relatively simple set of steps can be performed allowing nearly any file to have its content changed, even if that file has permissions and/or ownership settings restricting such actions. For example, using the write_anything proof of concept code from the above-linked article, we will build an image using this Dockerfile:

wordpress-sync/blog-dirty-pipe-dockerfile

Next, we run it in read-only mode and use the write_anything executable to change /etc/passwd.

wordpress-sync/blog-dirty-pipe-write-anything

I should not have been able to do this because the file is read-only and is both owned by root and is on a read-only root filesystem.

Next, let’s kill and remove this container, start a new one, and then take a look at /etc/passwd in the new container.

wordpress-sync/blog-dirty-pipe-snap

The file change persisted because the actual image layer contents, which are read-only on the host system, were modified by the previous container process. This change will persist on this host until the image is removed and/or replaced.

Low level image layer before running the hack

wordpress-sync/blog-dirty-pipe-before

Low level image layer after running the hack

wordpress-sync/blog-dirty-pipe-after

In fact, if you have multiple containers running on the same host, a change like this may immediately be seen by any container that shares this base image layer (with the exception of any that have made a modification to the same file in their own r/w layer already).

Three containers running with a watch on their /etc/passwd files as a fourth container runs the write_anywhere hack.

wordpress-sync/blog-dirty-pipe-watch

All your host mounted volumes are belong to Dirty Pipe

wordpress-sync/blog-dirty-pipe-all-your-base

As you may have heard, mounting host volumes (a.k.a. bind-mounts) into your containers is never a good idea. Under normal circumstances, this is advised because a simple misconfiguration could grant the container unintended access to modify files on the host. Dirty Pipe raises the stakes on this issue because host mounted volumes are at risk using this exploit, even if the volume was mounted with the :ro flag set.

wordpress-sync/blog-dirty-pipe-blind

Privilege escalation via Dirty Pipe

One of the exploit proof-of-concept examples making the rounds uses this flaw to gain elevated privileges by modifying an existing suid-enabled binary to bypass the normal protections against such a thing. This is not a container-specific concern but it can be used inside your containers. A theoretical example of this would be if an attacker were to exploit a remote code execution (RCE) vulnerability in an application and inject this POC code to become root in your container. This effectively bypasses the use of container and/or Kubernetes settings limiting such behavior.

Are there any mitigations?

As we mentioned above, upgrading your host systems is the only known way to protect your systems from this vulnerability. Container engines and Kubernetes mitigations are simply at too high of a level to provide much protection from a kernel-level exploit like this.

Can’t we just update our base images?

Unfortunately, no. The flaw is not in the filesystem of any of the base images, but rather in the kernel of the hosting servers which is shared between all running containers. You can see this by running uname -a in a mix of containers from different base images; they will all report the kernel version from the host.

wordpress-sync/blog-dirty-pipe-base

What about Kubernetes SecurityContext?

Kubernetes SecurityContext settings such as readonlyRootFilesystem:true, runAsNonRoot:true, runAsUser:, and AllowPrivilegeEscalation:false are all ineffective because any user can leverage this vulnerability and bypass these settings.

This is not to say you shouldn’t use these settings. On the contrary, they are excellent examples of practicing defense-in-depth and will protect your clusters from many other attack types.

In fact, we have a Kubernetes security cheat sheet that discusses the SecurityContext settings and why you should be using them to harden your Kubernetes application deployments. You also can scan your Kubernetes manifests using Snyk’s free IaC scanning tools to help you find and fix misconfigurations like these. Click the link below to start using it today.

Wrapping Up

If you haven’t done so already, update your hosts immediately and if any of the above topics piqued your interest, check out the following links for a deeper dive.

wordpress-sync/blog-feature-security-alert-purple

パイプラインをセキュアにするための8つのヒント

これらの8つの実践的なスキャン・統合のアドバイスを用いて、プロダクションへの公開前にパイプライン上のセキュリティ問題を検出しましょう。