5

CVE-2023-28432 Minio信息泄露导致RCE

 1 year ago
source link: https://y4er.com/posts/minio-cve-2023-28432/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

CVE-2023-28432 Minio信息泄露导致RCE

 2023-03-24  2023-03-24  约 1338 字   预计阅读 3 分钟 

https://github.com/minio/minio/security/advisories/GHSA-6xvq-wj2x-3h3q

这通告把漏洞点都给出来了…

看这篇文章《Docker下MinIO的使用》

docker-compose.yml

version: '3.7'

# starts 4 docker containers running minio server instances. Each
# minio server's web interface will be accessible on the host at port
# 9001 through 9004.
services:
  minio1:
    image: minio/minio:RELEASE.2020-01-16T22-40-29Z
    container_name: minio1
    volumes:
      - data1-1:/data1
      - data1-2:/data2
    ports:
      - "9001:9000"
    environment:
      MINIO_ACCESS_KEY: minio
      MINIO_SECRET_KEY: minio123
    command: server http://minio{1...4}/data{1...2}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3

  minio2:
    image: minio/minio:RELEASE.2020-01-16T22-40-29Z
    container_name: minio2
    volumes:
      - data2-1:/data1
      - data2-2:/data2
    ports:
      - "9002:9000"
    environment:
      MINIO_ACCESS_KEY: minio
      MINIO_SECRET_KEY: minio123
    command: server http://minio{1...4}/data{1...2}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3

  minio3:
    image: minio/minio:RELEASE.2020-01-16T22-40-29Z
    container_name: minio3
    volumes:
      - data3-1:/data1
      - data3-2:/data2
    ports:
      - "9003:9000"
    environment:
      MINIO_ACCESS_KEY: minio
      MINIO_SECRET_KEY: minio123
    command: server http://minio{1...4}/data{1...2}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3

  minio4:
    image: minio/minio:RELEASE.2020-01-16T22-40-29Z
    container_name: minio4
    volumes:
      - data4-1:/data1
      - data4-2:/data2
    ports:
      - "9004:9000"
    environment:
      MINIO_ACCESS_KEY: minio
      MINIO_SECRET_KEY: minio123
    command: server http://minio{1...4}/data{1...2}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3

## By default this config uses default local driver,
## For custom volumes replace with volume driver configuration.
volumes:
  data1-1:
  data1-2:
  data2-1:
  data2-2:
  data3-1:
  data3-2:
  data4-1:
  data4-2:
docker-compose pull
docker-compose up

http://172.16.16.128:9001/ 到9004端口都是minio集群

根据官方GitHub中的通告 https://github.com/minio/minio/security/advisories/GHSA-6xvq-wj2x-3h3q 可知

在集群部署中,MinIO返回所有环境变量,包括MINIO_SECRET_KEY和MINIO_ROOT_PASSWORD,导致信息泄露。

// minio/cmd/bootstrap-peer-server.go
func (b *bootstrapRESTServer) VerifyHandler(w http.ResponseWriter, r *http.Request) {
  ctx := newContext(r, w, "VerifyHandler")
  cfg := getServerSystemCfg()
  logger.LogIf(ctx, json.NewEncoder(w).Encode(&cfg))
}

// minio/cmd/bootstrap-peer-server.go
func getServerSystemCfg() ServerSystemConfig {
  envs := env.List("MINIO_")
  envValues := make(map[string]string, len(envs))
  for _, envK := range envs {
    // skip certain environment variables as part
    // of the whitelist and could be configured
    // differently on each nodes, update skipEnvs()
    // map if there are such environment values
    if _, ok := skipEnvs[envK]; ok {
      continue
    }
    envValues[envK] = env.Get(envK, "")
  }
  return ServerSystemConfig{
    MinioEndpoints: globalEndpoints,
    MinioEnv:       envValues,
  }
}

给出了补丁的commit https://github.com/minio/minio/commit/3b5dbf90468b874e99253d241d16d175c2454077

diff可见增加了敏感字段skip的操作

https://y4er.com/img/uploads/minio-CVE-2023-28432/1.png

最终路由映射到 http://172.16.16.128:9001/minio/bootstrap/v1/verify

https://y4er.com/img/uploads/minio-CVE-2023-28432/2.png

cmd/routers.go:75 判断了一下是集群才会注册上述路由

https://y4er.com/img/uploads/minio-CVE-2023-28432/3.png
curl -XPOST http://172.16.16.128:9001/minio/bootstrap/v1/verify

minio是个go写的项目,go rce的方式不是很多,我的思路是找自更新的点。

在这个commit中 https://github.com/minio/minio/commit/05444a0f6af8389b9bb85280fc31337c556d4300

加了一个二进制文件签名校验

https://y4er.com/img/uploads/minio-CVE-2023-28432/4.png

这个函数在cmd/admin-handlers.go ServerUpdateHandler函数中被调用,对应的路由为POST /minio/admin/v3/update?updateURL={updateURL} 有一些版本好像是v2

ServerUpdateHandler函数中经过了几个处理,代码比较长,我贴一下精简之后的。

func (a adminAPIHandlers) ServerUpdateHandler(w http.ResponseWriter, r *http.Request) {
	// 验证是否是admin权限
	objectAPI, _ := validateAdminReq(ctx, w, r, iampolicy.ServerUpdateAdminAction)

	// 从POST /minio/admin/v3/update?updateURL={updateURL}取updateURL参数
	vars := mux.Vars(r)
	updateURL := vars["updateURL"]
	mode := getMinioMode()

	// 解析url
	u, err := url.Parse(updateURL)

	// 下载Release信息并解析出对应的更新信息
	content, err := downloadReleaseURL(u, updateTimeout, mode)
	sha256Sum, lrTime, releaseInfo, err := parseReleaseData(content)

	// 指定二进制文件的下载路径
	u.Path = path.Dir(u.Path) + SlashSeparator + releaseInfo

	// 下载二进制文件
	reader, err := downloadBinary(u, mode)

	// 验证签名
	err = verifyBinary(u, sha256Sum, releaseInfo, mode, reader)

	// 提交二进制文件
	err = commitBinary()

	// 发送重启信号给channel
	globalServiceSignalCh <- serviceRestart
}

而在verifyBinary中envMinisignPubKey环境变量应该是默认为空,导致签名校验无效。

https://y4er.com/img/uploads/minio-CVE-2023-28432/5.png

攻击者可以伪造updateURL来触发恶意自更新来执行任意二进制文件,不过这个动静可能有点大,而且恶意二进制文件应该是针对minio二开的,否则服务可能会挂掉。

最后一点,就是如何使用敏感信息泄露的用户来提权到admin用户。

commit应该是67f4ba154a27a1b06e48bfabda38355a010dfca5 看了下没看懂,先放一放,让子弹飞一会。

r师太吊了,打call。

文笔垃圾,措辞轻浮,内容浅显,操作生疏。不足之处欢迎大师傅们指点和纠正,感激不尽。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK