CVE-2021-30465:runc 竞争致 docker 逃逸

基础知识

在容器层面挂载卷和挂载目录是不一样的。

挂载目录,对容器来说,只是简单把目录与容器的目录做映射绑定,而目录的权限还是在主机,需要用户自制维护,手动处理权限等问题。

卷 (Volume) 是受控存储,挂载卷后是由容器引擎进行管理维护的,也就是把对应卷的所有权交给了容器引擎(本次漏洞的核心点)

正常定义卷A之后 ,若a容器挂载了卷A,那它同时也挂载了卷A下面的目录。

当a容器起来后,恶意程序疯狂的在挂载的目录下刷新软连接与目录的关系。与此同时若b容器也像a容器一样挂载了相同中的卷和对应卷下面的目录。

因为卷所有权这个时候是在引擎内,并且a容器相同卷下的目录还在刷新软连接(相同于创建软连接)这个时间在容器引擎内部就会存在资源竞争,形成了漏洞。

漏洞原理

runc在处理容器卷挂载时,会先使用filepath-securejoin库检查并解析路径中的符号链接以确保安全性,但这一“检查”动作与后续实际执行挂载的“使用”动作并非原子操作,其间存在一个极小的可被攻击的时间窗口。攻击者可在Kubernetes这类支持多容器共享卷的环境中,创建一个包含恶意容器与受害者容器的Pod,并利用符号链接交换(symlink-exchange)手法,在runc完成路径安全检查之后、执行挂载操作之前,迅速将共享卷中的目标目录替换为指向宿主机根目录的符号链接,从而诱骗runc在毫秒级的竞争窗口内将宿主机文件系统挂载进受害者容器,最终获得对宿主机文件的读写权限并实现逃逸。

漏洞对比

对比维度CVE-2021-30465 (runc 竞争致逃逸)CVE-2018-15664 (Docker CP 逃逸)
漏洞组件runc(容器运行时)Docker daemon(API 及 docker cp 命令)
攻击触发方式容器创建/启动时,通过构造恶意卷配置触发容器运行中,通过劫持外部发起的 docker cp 操作触发
攻击者前提需要创建多个容器并配置共享卷需要拥有执行 docker cp 命令的权限
攻击目标宿主机根目录挂载为容器内的一个卷宿主机文件系统进行任意读写(读或写任意文件)
影响范围runc < 1.0.0-rc95Docker 17.06.0-ce 至 18.06.1-ce-rc2
修复状态升级 runc 到 v1.0.0-rc95 或更高版本官方提供了临时方案(如使用 docker pause),根本性修复需修改 Docker 底层逻辑
利用难度较高:需要精确的时间窗口,在特定场景(如K8s)下更易实现相对较低:有公开的、稳定的PoC,攻击路径更直接
漏洞利用结果容器逃逸,获得对宿主机文件的读/写访问权限容器逃逸,获得对宿主机文件的读/写访问权限

漏洞利用

创建攻击Pod

image-20260908154833296

编译恶意程序

image-20260908155048186

执行恶意程序

将恶意程序拷贝至c1容器内执行

image-20260908155735856

进入 c1 容器创建符号链接并执行攻击脚本

image-20260908161417395

接着更新c2-c20的容器镜像为合法镜像。新打开一个终端,执行以下命令更新镜像,一旦更新,pod会尝试创建容器

image-20260908163418320

利用成功

image-20260908163641569

标签: none

添加新评论

邮箱仅用于识别回复,不会在页面公开。提交后请等待页面确认结果。

文章图片预览