runc 文件描述符泄漏导致容器逃逸漏洞

 人参与 | 时间:2026-10-17 06:54:02

2022年,文件安全研究员leaktest在runc的描述代码里发现了一个诡异的细节。这个负责创建和运行容器的符泄底层工具,在调用`execve`系统调用时,漏导居然没有关闭传递给它的致容文件描述符。这个看似不起眼的器逃疏忽,直接导致了一个严重的逸漏容器逃逸漏洞——攻击者可以在容器内拿到宿主机的控制权。

要理解这个漏洞,文件得先明白runc的描述工作方式。它像是符泄一个严格的管家,容器里的漏导进程是客人,文件描述符则是致容房间钥匙。正常情况下,器逃管家在把钥匙交给客人之前,逸漏会把所有多余的文件钥匙都收走。但这次,管家漏掉了一把。

具体来说,当你在容器里执行`docker exec`命令时,runc会创建一个新的进程,并把标准输入输出错误这三个文件描述符传进去。问题出在,runc还额外传递了一个指向自身配置文件的文件描述符——这个文件通常位于宿主机的`/run/runc`目录下,权限是root所有。

攻击者要做的事情就变得简单了。在容器内,通过`/proc/self/fd`目录,可以找到这个泄露的文件描述符。拿到它之后,攻击者可以读取宿主机上的文件内容,甚至更狠一点——如果宿主机上运行着其他容器,攻击者可以尝试修改这个文件描述符指向的文件,从而干扰其他容器的运行。

但真正的杀招在别处。runc在启动容器进程时,会先执行一个名为`runc init`的辅助进程。这个进程会通过一个Unix socket与主进程通信,而这个socket的文件描述符也被泄露了。攻击者如果抢在主进程之前,往这个socket里写入恶意数据,就能让runc执行任意代码——这等于直接拿到了宿主机的root权限。

这个漏洞的利用条件不算苛刻。攻击者只需要在容器内有基本的执行权限,不需要额外的capabilities,也不需要特殊的挂载设置。换句话说,任何一个能运行`docker exec`的用户,理论上都能利用这个漏洞逃逸出容器。

修复方案倒是简单粗暴——在runc的源码里,在调用`execve`之前,把所有多余的文件描述符都设置为`FD_CLOEXEC`标志。这个标志的意思是,当进程执行新程序时,这些文件描述符会自动关闭。一行代码的改动,堵住了这个致命的漏洞。

这个漏洞让我想起之前CVE-2019-5736,同样是runc的问题,同样是文件描述符处理不当。两年的时间里,runc团队修复了一个又一个类似的问题,但底层工具的安全性依然脆弱。容器技术号称轻量级隔离,但隔离的边界往往就藏在这些容易被忽视的细节里。

对运维人员来说,这个漏洞的启示很直接——别以为容器天然安全。及时更新runc到修复版本,是唯一的办法。如果你还在用老版本的Docker或者containerd,现在就该去检查一下了。

顶: 658踩: 9