一. MinIO Architecture
二. Research Strategy
三. The Vulnerabilities
(1) Privilege Escalation under Windows
(2) Privilege Escalation under Linux/MacOS
(3)Information Disclosure under Cluster Deployment
(4)File Operation under Cluster Deployment
(5)Misconfiguration leads Remote Code Execution
四. The Exploitation
MinIO 是一个Golang编写的对象储存服务,兼容Amazon S3的服务接口。MinIO支持多个操作系统,包括Linux、Windows、MacOS等,同时支持集群部署和单机部署,也集成了K8S、OpenShift等云计算平台。
MinIO 服务架构分为储存桶服务(S3 API)、Console API、Admin API,对于集群部署,还提供了部分API进行集群信息通讯。MinIO 的S3 API和Admin API都默认位于9000端口,无法关闭,而Console API可以通过MINIO_BROWSER 环境变量进行控制关闭。
MinIO 所有的配置都通过环境变量和.minio.sys储存桶储存控制,此储存桶在代码层面被保护从而禁止访问。桶内数据同样遵循其他普通储存桶的数据储存结构。
MinIO 用户凭据分为四种,分别是root用户、普通用户、服务帐号、STS(Security Token Service)。
-
root 用户需要通过环境变量MINIO_ROOT_USER 设置,此用户的凭证也是内部服务认证的唯一凭证,包括但不限于集群同步、JWT 签名等操作。
-
普通用户可以通过Console API添加,其信息储存在.minio.sys的config/iam/users 中,此类用户可以赋予其相应的policy来获得对应的权限。
-
服务帐号为root用户和普通用户申请的子凭据(Access Key/Secret Key),可以继承用户的权限,其信息储存在config/iam/service-accounts中。
-
STS 和服务帐号的角色相同,但是为由以上三种用户类型临时申请的凭据,其信息储存在config/iam/sts中。
MinIO的API基本上都是针对储存桶的增删查改操作,如果以RCE为目标会颇有难度,所以我开始针对MinIO的研究目的主要是对于其文件系统的任意文件写。
同时在默认情况下,匿名用户无法上传文件至储存桶中,所以研究的前提为存在一个低权限的可读写凭据的情况下,针对MinIO的以下几点进行相关的研究:
-
针对 Admin API的研究,包括越权、提权、目录遍历、逻辑漏洞、RCE等;
-
针对 Console API 的研究,主要是其提供的功能是否存在 RCE 的可能性;
-
针对 Object 的操作过程中是否存在任意文件写、任意文件读取、逻辑漏洞等;
1. Privilege Escalation under Windows
MinIO 对 Windows 环境下的目录过滤不严,导致可以利用 实现目录遍历,从而导致任意文件写入,继而导致提权。此利用仅需要拥有一个可 PubObject 的 bucket 的情况下即可利用,不限制用户类型。
MinIO 存在全局的请求数据判断,针对 GET 的 query data 以及路径以 / 分隔后,判断每一段路径中是否包含了 ..:
但是对于 Windows 环境,可以使用 分隔来绕过此处的判断,达到目录穿越的效果。在实际利用的过程中,可以向 .minio.sys 写入相关数据实现增加用户,代码如下:
2. Privilege Escalation under Linux/MacOS
MinIO 在处理PostPolicyBucket操作时,在前期处理存在逻辑问题导致可以绕过对于.minio.sys 储存桶的代码层面限制,实现对于此储存桶的操作。此利用需要一个拥有对于arn:aws:s3:::* 的操作权限的任意用户类型,同时需要开启 Console API(默认开启)。
MinIO 在此处进行检查用户是否请求.minio.sys储存桶,但是如果不满足一下条件则不会报错:
其中,guessIsBrowserReq 的代码如下:
可见当开启了 MINIO_BROWSER 且 aType 为匿名的情况下可以通过判断。
但是在判断是否为匿名之前,首先使用isRequestPostPolicySignatureV4 判断了是不是 PostPolicy 请求,而我们的请求的API确实是PostPolicy,所以我们需要绕过这个判断,其代码如下:
可以发现此处判断了 Content-Type 是否包含了 multipart/form-data,而对于 PostPolicy 的 Router 如下:
此处利用了正则判断 Content-Type 是否以 multipart/form-data 开头,通过经验判断可以通过大小写来绕过 isRequestPostPolicySignatureV4 的检查,但是又可以成功匹配到这个路由。
成功绕过对于 .minio.sys 储存桶的限制后,就可以实现对于此储存桶的 PostPolicy 操作了,通过分析 PostPolicy 的代码,发现在经过一系列的检查后(包括对于凭据合法性的检查和内容的签名等),会向此储存桶进行 PostObject 操作:
于是这里就可以利用此处的PutObject对.minio.sys储存桶进行修改从而实现增加用户。但是对于此储存桶操作需要拥有arn:aws:s3:::*的操作权限,所以有部分限制。
3. Information Disclosure under Cluster Deployment
在集群部署环境下,在bootstrap API 中,MinIO 错误的导出了所有的所有的环境变量,导致了其关键的 MINIO_ACCESS_KEY、MINIO_SECRET_KEY(或者MINIO_ROOT_USER、MINIO_ROOT_PASSWORD)泄漏,从而导致攻击者获取完整的MinIO权限。
利用方式如下:
4. Misconfiguration leads Remote Code Execution
MinIO 在未配置 MINIO_UPDATE_MINISIGN_PUBKEY 的情况下,可以实现利用 Admin API 从恶意源更新并重新启动 minio 程序,导致 RCE。
MinIO 提供了更新 minio 程序的 Admin API,此处的关键代码如下:
通过下载传入的 updateURL 所提供的 release 文件进行解析后,接着下载对应的 binary 文件,验证签名后储存,同时发送信号进行服务重启。其中验证签名的代码如下:
可见当未设置 MINIO_UPDATE_MINISIGN_PUBKEY环境变量时,则不会进行binary 的签名验证,所以可以实现利用此处的配置不当实现RCE。
当binary文件下载完成时,会将原本的binary文件重命名为.{filename}.old,如果想恢复原本的MinIO服务,需要调用一下原本的binary,利用代码如下:
针对以上出现的漏洞,在利用过程中,首先要获取到一个任意权限的凭据,接着根据凭据类型进行提权。在 public 储存桶存在的情况下,在 Windows 下不需要任何凭据即可进行利用。但是在 Linux 下,由于无法通过目录遍历绕过权限检查的逻辑,所以需要一个 arn:aws:s3:::* 有可读写权限的用户凭据进行利用。
提权之后,可以利用高权限的用户凭据创建储存桶并上传相应的release信息和利用程序,这样可以避免出网。最后,利用升级功能覆盖原本的minio二进制文件,实现远程命令执行。
原文始发于微信公众号(黑伞安全):【Real World CTF 6th Writeup】MinIO Research and Exploitation