CVE-2019-3799 Spring-Cloud-Config-Server 路径穿越/任意文件读取

警告
本文最后更新于 2020-06-05,文中内容可能已过时。

Spring的一些洞

idea创建一个spring项目,然后pom.xml中加入

1
2
3
4
5
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
    <version>2.0.2.RELEASE</version>
</dependency>

配置application.properties

1
2
server.port=8888
spring.cloud.config.server.git.uri=https://github.com/SukaraLin/awesome-cve-poc.git

然后访问 http://127.0.0.1:8888/aaa/bbb/master/..%252F..%252F..%252F..%252F..%252F..%252Fwindows/win.ini

image.png

Spring Cloud Config Server是Spring为了分布式管理的一个组件,在Server端中负责存储配置,Client可以通过http的形式获取配置值。payload对应的路由存在于org.springframework.cloud.config.server.resource.ResourceController#retrieve()中,其代码

1
2
3
4
5
    @RequestMapping({"/{name}/{profile}/{label}/**"})
    public String retrieve(@PathVariable String name, @PathVariable String profile, @PathVariable String label, HttpServletRequest request, @RequestParam(defaultValue = "true") boolean resolvePlaceholders) throws IOException {
        String path = this.getFilePath(request, name, profile, label);
        return this.retrieve(name, profile, label, path, resolvePlaceholders);
    }

{name}/{profile}/{label}:name对应仓库名,profile对应配置文件,label为git分支名,一般上都有一个master分支。实际测试中name、profile值无所谓,但是label分支名必须存在。调试跟进getFilePath

image.png

这边已经把%25urldecode为%了,继续跟retrieve(),这边path传入的是我们的payload

image.png

继续跟下findOne,位于org.springframework.cloud.config.server.resource.GenericResourceRepository#findOne

image.png

locations目录file:/C:/Users/icu/AppData/Local/Temp/config-repo-6608031716294156148/是配置文件中git仓库被clone的临时位置,然后拼接../造成跨目录文件读取。

https://github.com/spring-cloud/spring-cloud-config/commit/3632fc6f64e567286c42c5a2f1b8142bfde505c2

image.png

通过判断是否存在%来urldecode,然后匹配../../等特殊字符。

  1. Spring-Cloud-Config-Server-任意文件读取分析

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