Spring Cloud Config目录穿越漏洞(CVE-2020-5045)代码审计

漏洞简介

Spring Cloud Config为分布式系统的外部配置提供客户端的服务端的支持。使用它,开发人员就可以在一个中心仓库管理应用程序在所有环境中的外部配置。

Spring Cloud Config,2.2.3之前的2.2.x版本,2.1.9之前的2.1.x版本以及较旧的不受支持的版本允许应用程序通过spring-cloud-config-server模块提供任意配置文件。恶意用户或攻击者可以使用特制URL发送请求,这可能导致目录遍历攻击(在配置仓库为本地native的情况下,攻击者可以获取config-server服务器上的任意带后缀文件。)

Spring cloud Config有三次目录穿越漏洞,分别是CVE-2019-3799,CVE-2020-5405和CVE-2020-5410,可参考文章:https://xz.aliyun.com/t/7558https://xz.aliyun.com/t/7877

利用条件:

  • 修改配置文件src/main/resources/configserver.yml
  • 主要是设置profiles.active为native,设置search-locations为任意文件夹

影响版本:

  • 2.2.x prior to 2.2.2
  • 2.1.x prior to 2.1.7

漏洞复现

环境搭建:

1.从github下载spring-cloud-config模块:https://github.com/spring-cloud/spring-cloud-config/archive/v2.1.5.RELEASE.zip

2.将文件夹中的spring-cloud-config-server模块导入IDEA中(这是一个Maven+SpringBoot项目)

3.修改配置文件src/main/resources/configserver.yml

​ 设置profiles.active为native,并设置search-locations为任意文件夹

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
info:
  component: Config Server
spring:
  application:
    name: configserver
  autoconfigure.exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
  jmx:
    default_domain: cloud.config.server
  profiles:
    active: native
  cloud:
    config:
      server:
        native:
          search-locations:
            - file:/Users/xps/Desktop/test1
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          repos:
            - patterns: multi-repo-demo-*
              uri: https://github.com/spring-cloud-samples/config-repo

server:
  port: 8888
management:
  context_path: /admin

image-20240809193244862

4.启动项目:启动ConfigServerApplication类,然后访问127.0.0.1:8888

5.测试payload:

1
2
3
4
5
http://127.0.0.1:8888/1/1/..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29/1.txt	# 使用这个
http://127.0.0.1:8888/1/1/..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29/etc/passwd

# 编码之前是
http://127.0.0.1:8888/1/1/..(_)..(_)..(_)..(_)..(_)..(_)..(_)..(_)/1.txt

成功跨越目录读取文件

image-20240809194404384

漏洞分析:

Config Server通过路径/{name}/{profile}/{label}/{path}对外提供配置文件,POC会通过路由到这个接口

所以我们先看下org\springframework\cloud\config\server\resource\ResourceController.java并打上断点

1
2
3
4
# 三个参数的含义
name:仓库名称
profile:配置文件环境(dev,test,pro)
label:分支(

可以看到name、profile、label的值:

image-20240809195714301

path通过getFilePath获取,跟进:

image-20240809200017725

image-20240809200048609

image-20240809200133018

可以看到getFilePath方法中将解析我们传入的文件名给path,然后返回

image-20240809200324371

返回到原来断点位置,可以看到getFilePath方法返回的path值会传入retrieve方法,跟进retrieve方法:

image-20240809200416581

可以看到,分别将name和label传入了resolveNameresolveLabel

跟进resolveName

作用是将(_)替换成/,但是我们name是不含这个的,不满足,直接返回

image-20240809200543258

跟进resolveLabel

作用跟resolveName是同样的,不过这里label中包含(_),所以满足,进行替换

image-20240809200620617

所以我们的数据被替换成了 ../../../../../../../../../

image-20240809200737081

继续回到retrieve往下跟,程序执行到findOne方法,跟进:

image-20240809200935300

可以看到这个方法中this.service.getLocations是调用配置文件(也就是我们之前配置文件中配置的search-locations):

image-20240809201043879

然后跟我们传入的参数重新拼接,得到两个路径:

image-20240809201210399

getProfilePaths方法是根据profile构造文件路径:

image-20240809201359474

然后在下边使用isInvalidPath进行非法路径的判断,但是这个判断是针对path的,而我们的payload是在label中,所以可以绕过:

image-20240809201520772

参考文章

https://xz.aliyun.com/t/7877

https://www.freebuf.com/vuls/325595.html

0%