[备份]CVE-2020-5405分析

简介

Spring Cloud Config微服务架构的配置中心,为各个不同服务提供了一个中心化的外部配置。不适用本地配置是因为集群间不方便管理,需要一个平台,通常是从github等平台拉取配置。之前在字节工作,他们用的TCC平台,也是一个类似Spring Cloud Config的配置中心

Spring Cloud Config分为服务端和客户端两部分:

这个漏洞不是RCE,是目录遍历,不算高危

漏洞复现

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

导入IDEA其中的spring-cloud-config-server模块,Maven+SpringBoot项目

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

ConfigServerApplication类启动,访问localhost:8888

手动在D:/Code下创建一个key.txt,尝试读取这个文件

Payload: http://127.0.0.1:8888/1/1/..(_)..(_)..(_)..(_)..(_)..(_)..(_)..(_)..(_)Code/key.txt

http://127.0.0.1:8888/1/1/..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29Code/key.txt(编码后) img

漏洞分析

Config Server通过路径/{name}/{profile}/{label}/{path}对外提供配置文件,POC会通过路由到这个接口,参考org\springframework\cloud\config\server\resource\ResourceController.java

下断点查看这一步的name和profile等变量分别是什么 img

Payload: /1/1/..(_)..(_)..(_)..(_)..(_)..(_)..(_)..(_)..(_)Code/key.txt

不难看出getFilePath方法作用是解析**为key.txt

最后调用retrieve方法

其中的resolveName和resolveLabel方法作用一致,都是将(_)换成/

所以到达findOne方法这里:

this.service.getLocations方法应该是调用配置文件并重新拼接,最终得到两个路径,其中第1(2)个是我们的payload img

后面的getProfilePaths方法是根据profile构造文件路径。这个主要是参照日常习惯,比如开发配置文件会命名为confg-dev.yaml这样 img

其实程序做了非法路径的判断:isInvalidPath,不过它校验的path,而我们的path是key.txt,不是违法的路径

另一个编码校验自然也无效

最后通过this.resourceLoader.getResource(location).createRelative(local);加载了本地文件,这个没必要跟踪,已经确认了过程

 

漏洞修复

补丁:https://github.com/spring-cloud/spring-cloud-config/commit/651f458919c40ef9a5e93e7d76bf98575910fad0

补丁对location进行了验证,而不只是简单地对path做验证

实际中也确实应该对最后一步的输入进行判断,而不只是对过程进行判断