本文档说明所提供的 runc 漏洞 CVE-2025-31133 的 Proof-of-Concept (PoC) 脚本的功能。
runc 中 maskedPaths 处理的一个符号链接条件竞争漏洞。maskedPaths 的保护,从而允许写入宿主机上的敏感文件。这构成了一次容器逃逸。/proc/sys/kernel/core_pattern 文件。"pwned",并且不在宿主机上执行任意代码。它还提供了恢复原始值的说明。容器的 OCI 规范 (config.json) 中的 maskedPaths 功能是一种安全机制,旨在防止容器访问敏感的宿主系统文件。其工作原理是将 /dev/null(一个空设备文件)通过绑定挂载覆盖容器内的敏感路径,从而使其无法读取和写入。
漏洞 (CVE-2025-31133) 是一个检查时间到使用时间 (TOCTOU) 的竞争条件。利用过程如下:
runc 设置容器时,它准备使用容器根文件系统中的 dev/null 文件作为绑定挂载的源,以遮蔽敏感路径(例如 /proc/sys/kernel/core_pattern)。runc 解析 rootfs/dev/null 的路径与实际执行挂载操作之间存在一个短暂的时间窗口。rootfs/dev/null 文件,使其在合法的设备节点和指向宿主机目标文件 (/proc/sys/kernel/core_pattern) 的符号链接之间切换。runc 会在 rootfs/dev/null 恰好是符号链接的那一刻执行挂载操作。这导致内核跟随符号链接,从而针对 /proc/sys/kernel/core_pattern 的预期遮蔽操作失败。/proc/sys/kernel/core_pattern,这会直接修改宿主机的文件,实现容器逃逸。此 PoC 利用此技术写入 /proc/sys/kernel/core_pattern,这是一个常见的目标,因为修改它可以在进程崩溃时导致宿主机上执行任意代码。然而,此 PoC 仅写入一个无害字符串,以证明写入原语的存在。
poc.sh 脚本自动执行上述整个过程。
设置与清理:
runc 二进制、容器名称和根文件系统路径的变量。cleanup 函数,确保删除脚本先前创建的任何容器或文件。该函数在退出、中断或终止时自动调用。准备:
/proc/sys/kernel/core_pattern 的原始内容保存到一个临时文件中。稍后用于验证利用是否成功,并帮助用户恢复系统。./rootfs) 和一个 config.json 文件。config.json 在 maskedPaths 中显式列出 /proc/sys/kernel/core_pattern——这正是该利用试图绕过的功能。竞争函数 (symlink_race)
rootfs/dev/null。rootfs/dev/null 到目标宿主机文件 (/proc/sys/kernel/core_pattern) 的符号链接。mknod 将 rootfs/dev/null 重新创建为一个正确的字符设备。执行:
symlink_race 函数作为后台进程启动。runc run ... 来创建并启动容器。这是 runc 尝试应用 maskedPaths 的时刻。runc exec 在容器内部执行命令:echo 'pwned' > /proc/sys/kernel/core_pattern。验证:
/proc/sys/kernel/core_pattern 的当前内容。"pwned" 字符串以及原始值进行比较。[+] EXPLOIT SUCCEEDED! 或 [-] Exploit did not succeed. 消息。前提条件:
runc。busybox-static(用于容器的 Shell)。sudo) 以运行 runc 和修改 /proc。步骤:
poc.sh。chmod +x poc.sh。sudo ./poc.sh。[+] EXPLOIT SUCCEEDED! 消息,说明竞争条件获胜。宿主机上的 /proc/sys/kernel/core_pattern 已成功从容器内部被修改,确认了漏洞存在。[-] Exploit did not succeed.,表示本次尝试未赢得竞争。竞争条件是概率性的,严重依赖于系统时序和负载。请多运行几次脚本。PoC 会修改一个系统文件。要将其恢复为原始状态,请运行脚本提示的命令:
# 原值 'ORIGINAL_PATTERN' 将是你系统中的实际值
echo 'original_core_pattern_value' | sudo tee /proc/sys/kernel/core_pattern