CVE-2020-15257(containerd逃逸)
影响版本
containerd <1.3.9 或 <1.4.3
漏洞原理
containerd 是 Docker 等容器平台的核心运行时组件,其架构中包含containerd-shim进程,负责中间层管理(如进程监控、信号转发、IO 重定向等),隔离 containerd 主进程与容器进程。containerd<->containerd-shim<->runc
攻击者可通过恶意容器构造特殊进程,利用 containerd-shim
进程的文件描述符(FD)管理缺陷,获取宿主机的敏感文件描述符,最终实现容器逃逸并访问宿主机资源。
shim 在处理子进程退出信号(SIGCHLD)时,未正确验证进程 PID 的归属,导致攻击者可伪造 PID 欺骗 shim,获取本应属于宿主机的文件描述符。
- shim 的进程管理逻辑: 当容器内进程退出时,内核会发送 SIGCHLD 信号给 shim,shim 通过
waitpid()
系统调用回收进程资源。此时,shim 会将该进程关联的文件描述符(如标准输入 / 输出的 FD)关闭。 - PID 验证缺陷: 正常情况下,shim 应只处理容器内的进程(即属于容器 PID 命名空间的进程)。但漏洞版本中,shim 未验证waitpid()返回的 PID 是否属于容器内的进程,而是直接处理所有 SIGCHLD 信号触发的进程回收,导致了漏洞的产生。
攻击者在容器内创建恶意进程,同时在宿主机侧构造同名 PID 的进程(通过命名空间逃逸或 PID 复用)。当宿主机侧进程退出时,shim 会错误地将其 FD 传递给容器内的恶意进程,导致容器内进程可访问宿主机的 FD(如宿主机的文件、设备等)。
环境搭建
1 | #卸载 |
1 | # 安装 containerd 1.3.7(漏洞版本) |
1 | docker run --name nginx-test --net=host -p 8080:80 -d nginx |
root 容器: 获取宿主机 FD 后,可直接读写宿主机的敏感文件(如修改/etc/sudoers
)或挂载设备,实现完整逃逸。
–net=host : 启动会暴露containerd-shim 监听的 Unix 域套接字,攻击者若能访问 containerd-shim 的 Unix 域套接字,可能:
- 发送伪造的进程退出信号,辅助触发 shim 的
wait4()
逻辑; - 通过套接字获取容器进程与 shim 的通信信息,更容易猜测或伪造 PID;
- 直接与 shim 交互,操纵其对 FD 的管理逻辑,加速文件描述符泄露。
漏洞复现
cdk 用旧版本的
此漏洞利用会导致 Docker/containerd 出现一些问题。其中会残留一个悬挂的 containerd-shim 和 Docker 容器,需要docker rm --force
分别将其终止和 d 以进行清理。
1 | #把工具放到容器里 |
1 | docker exec -it nginx-test /bin/bash |
修复方式
升级 containerd 至 1.3.10+ 或 1.4.4+