0x01 简介
该未授权访问漏洞是因为docker remote api可以执行docker命令,从官方文档可以看出,该接口是目的是取代docker 命令界面,通过url操作docker。
Docker remote Api未授权访问的攻击原理与之前的Redis未授权访问漏洞大同小异,都是通过向运行该应用的服务器写文件,从而拿到服务器的权限。
docker swarm是docker下的分布化应用的本地集群,在开放2375监听集群容器时,会调用这个api
当某个主机开放了2375端口时,就要注意了!
url输入ip:2375/version
就会列出基本信息,和docker version命令效果一样。
同样,url为ip:2375/v1.23/containers/json
会列出容器信息,和docker ps -a效果一样。
0x02 漏洞复现
通过docker客户端远程执行目标服务器容器命令:
1 列出所有镜像:
docker -H tcp://*.*.*.*:2375 images
2 列出所用容器
docker -H tcp://*.*.*.*:2375 ps -a
3 进入容器两种方法:
3.1 进入已有的容器
start 启动一个已经停止的容器
attach 连接一个已经停止的容器
当然这个容器默认entrypoint
必须是/bin/bash
,关于这点可以在json里看到,还有挂载,后面提权会用到,这个也可以在json文件里看到。
3.2 开启新容器
新运行一个容器并将entrypoint
设置为/bin/bash
,挂载点设置为服务器的根目录挂载至/mnt
目录下
注意:docker run
只在第一次运行时使用,将镜像放到容器中,以后再次启动这个容器时,只需要使用命令docker start
即可。
docker run
相当于执行了两步操作:将镜像放入容器中(docker create),然后将容器启动,使之变成运行时容器(docker start)。
wooyun上lijiejie是因为docker client版本不一致调用api去create重构一个容器,并在attach、start后捕获到输出
0x03 服务器提权的几种方法
1 写入SSH公钥
启动一个容器,挂载宿主机的/root/
目录,之后将攻击者的ssh公钥~/.ssh/id_rsa.pub
的内容写到入宿主机的/root/.ssh/authorized_keys
文件中,之后就可以用root账户直接登录了。
(1)本地获取ssh公钥
(2)将公钥复制到被攻击者的/root/.ssh/authorized_keys文件中
(3)ssh连接远程服务器
2 写入crontab反弹Shell
启动一个容器,挂载宿主机的/etc/目录,之后将反弹shell的脚本写入到/etc/crontab
中,攻击机nc -vv -l -p Port
会得到一个反弹的shell
攻击机上:
目标机上:
3 写入其他的cron中
也可以挂载var/spool/cron/
目录,将反弹shell的脚本写入到/var/spool/cron/root
(centos系统)或/var/spool/cron/crontabs/root
(ubuntu系统)
0x04 安全隐患
也许有运维同学觉得这是因为监听在了外网,所以攻击者才有机会攻击,如果我不监听在外网就没有安全隐患了,其实监听在内网也有以下安全隐患:
(1)外网攻击者可以通过WEB应用的SSRF漏洞,间接地攻击内网中的这些未授权的Docker remote api服务;
(2)方便已经攻入内网的攻击者扩大攻击范围;
(3)可能会被内部别有用心的人攻击,然后窃取敏感数据。
0x05 安全加固
在不必需的情况下,不要启用docker的remote api服务,如果必须使用的话,可以采用如下的加固方式:
1 设置ACL,仅允许信任的来源IP连接;
2 设置TLS认证,官方的文档为Protect the Docker daemon socket
客户端与服务器端通讯的证书生成后,可以通过以下命令启动docker daemon:
docker -d --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem --tlskey=server-key.pem -H=tcp://10.10.10.10:2375 -H unix:///var/run/docker.sock
客户端连接时需要设置以下环境变量
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=~/.docker
export DOCKER_HOST=tcp://10.10.10.10:2375
export DOCKER_API_VERSION=1.12