datadog3 min read

Curated summary

Escaping containers using the Dirty Pipe vulnerability | Datadog Security Labs

Read original(opens in new tab)

The post demonstrates how the Linux Dirty Pipe vulnerability can enable an unprivileged process to escape a container and gain administrative privileges on the host. The exploit abuses runC’s execution model and its host binary, which is exposed read-only inside the container but can still be modified through the kernel page cache. A proof of concept shows how a compromised Kubernetes pod can overwrite runC with a malicious executable when an administrator runs kubectl exec.

Container Runtimes and runC

  • Kubernetes commonly uses containerd or CRI-O through the Container Runtime Interface (CRI).
  • These runtimes rely on lower-level OCI runtimes, most notably runC, to create isolated Linux processes.
  • runC configures namespaces, cgroups, and the container environment before executing the supplied entrypoint with execve.
  • During execution, /proc/self/exe inside the container can refer to an open descriptor for the runC binary on the host.

Earlier runC Escape Vulnerability

  • CVE-2019-5736 exploited this /proc/self/exe behavior:
    • A malicious container entrypoint could write to the host’s runC binary.
    • Overwriting runC enabled subsequent container operations to execute attacker-controlled code with host-level privileges.
  • runC initially mitigated the issue by cloning its binary before execution.
  • It later changed the design to mount the runC binary read-only inside the container, improving performance through kernel page-cache sharing.
  • That optimization created conditions in which Dirty Pipe could bypass the apparent read-only protection.

Dirty Pipe as a Container Escape Primitive

  • Dirty Pipe allows an unprivileged process to overwrite files it can read, even without write permission.
  • The modification occurs in the kernel page cache rather than persistent storage:
    • The original file remains intact on disk.
    • Dropping caches or rebooting can restore the original contents.
  • Despite being temporary, the overwrite is sufficient to execute malicious code when the modified binary is run.
  • In this case, the attacker targets the host’s runC binary through /proc/<runC-pid>/exe.

Kubernetes Proof of Concept

  • The demonstration starts an ordinary, unprivileged pod using an attacker-controlled container image.
  • Its entrypoint script:
    • Replaces /bin/sh with a launcher referencing /proc/self/exe.
    • Waits for a runC process to appear.
    • Invokes the Dirty Pipe exploit against that process’s executable.
  • An administrator running kubectl exec causes runC to execute inside the container, triggering the overwrite.
  • The modified runC is replaced with a malicious ELF binary that runs commands such as id and hostname, recording their output in /tmp/hacked.
  • The exploit is adapted from the original Dirty Pipe proof of concept and the earlier runC escape technique.

The attack illustrates that kernel vulnerabilities can undermine container isolation even when the container is unprivileged and the target binary is mounted read-only. Systems should promptly patch vulnerable Linux kernels and container runtimes, while treating compromised containers as potential paths to host compromise.

Continue with another curated summary.