
Proof-of-concept for CVE-2024-21626, a runc container escape vulnerability. Includes verification scripts, two exploitation methods (cron reverse shell and command replacement), and analysis of the root cause and patch.
| Vulnerability Name | docker runc Escape Vulnerability |
|---|---|
| CVE ID | CVE-2024-21626 |
| Disclosure Date | 2024-01-31 |
| Characteristic | / |
| Affected Versions | runc @ [v1.0.0-rc93, 1.1.11] |
Exploitation Conditions are somewhat strict, requiring victim interaction. Personally, I find it a bit lackluster:
Verify Vulnerability and Obtain File Descriptor:
git clone https://github.com/V0WKeep3r/CVE-2024-21626-runcPOC.git
cd CVE-2024-21626-runcPOC
bash verify.sh
As shown below, the vulnerability exists, and the file descriptor is /proc/self/fd8
verify.sh can find the specific fd value corresponding to the current machine environment. If the fd is not 8, you need to modify the WORKDIR in the Dockerfile to the corresponding value or use -w in docker run to specify it.
Escape/Privilege Escalation Verification:
I designed this to be more practical. poc.sh uses a cron job to spawn a reverse shell.
poc2.sh uses command replacement (note: using this method requires backing up files in advance to avoid difficulty in recovery).
# 需要确认定时任务文件存在,不存在可以创建写,但是那样不能触发定时任务
# 只有crontab -e创建的,在crontab组的文件才会被定时执行。
docker build . -t poc1
docker run -it --rm poc1 bash /poc.sh

POC2:
docker build . -t poc2
docker run -it --rm poc2 bash /poc.sh
# 另起一个terminal
/bin/bash.copy

Not fully understood, but with the patch, we can get a general idea.
During the process of docker exec or docker run, runc's execve function is called. However, during runc exec, the file descriptor (fd) is not closed, causing the host's file descriptors to be leaked into the container environment. Users can use this file descriptor to read and write host files, thereby achieving container escape.
Fix Solution Upgrade runc to version 1.12 or above. Official runc link: https://github.com/opencontainers/runc/releases
Patch Analysis
Diff commit: https://github.com/opencontainers/runc/commit/2a4ed3e75b9e80d93d1836a9c4c1ebfa2b78870e
Close internal fds in time before execve.
In init_linux.go, after chdir, verify that cwd (current working directory) is inside the container.
