CVE-2020-5410 Spring Cloud Config目录遍历漏洞(新)

Spring Cloud Config,2.2.3之前的2.2.x版本,2.1.9之前的2.1.x版本以及较旧的不受支持的版本允许应用程序通过spring-cloud-config-server模块提供任意配置文件。

修复分析

对比2.2.2和2.2.3版本,发现其中有两个commits似乎和漏洞修复有关。

commits

查看对比发现在spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/EnvironmentController.java中多了一个pathUtils.isInvalidEncodedLocation判断。

diff-2.2.2

为了搞明白为什么要多加一个pathUtils.isInvalidEncodedLocation判断,查看Environment.normalize(),发现是将SLACH_PLACEHOLDER替换成/SLACH_PLACEHOLDER(_)。看到这里,是不是就想起了在CVE-2020-5405中利用(_)代替/绕过检测的方法。

1
2
3
4
5
6
7
8
public static String normalize(String s) {
if (s != null && s.contains(SLASH_PLACEHOLDER)) {
// "(_)" is uncommon in a git repo name, but "/" cannot be matched
// by Spring MVC
return s.replace(SLASH_PLACEHOLDER, "/");
}
return s;
}

利用分析

调试所使用版本为spring-cloud-config-2.2.2.RELEASE

和CVE-2020-5405一样需要,更将configserver.yml改成本地配置

和前面两个漏洞(CVE-2019-3799和CVE-2020-5405)类似,也是拼接了传入的值,而传入的值能够通过URL二次编码和(_)替换绕过路径检测,实现任意文件读取。但触发任意文件读取的函数和入口不一样。

EnvironmentController.java中找到getEnvironment方法,其中可控的参数为nameprofileslabel,调试步进findOne方法

debug-getEnvironment

NativeEnvironmentRepository.java中的getArgs中存在对我们可控参数nameprofileslabel的处理,步进该方法进行查看。

debug-findOne

getArgs()方法中看到熟悉的getLocations(),这里可能存在路径拼接

debug-getArgs

果然,在getLocations()方法中进行了路径的拼接,将locationlabel参数拼接在一起

debug-getLocations

光有location的拼接并不能产生文件读取,还得找到读取文件名的控制。

经过一段时间的调试,最终发现在builder.run中发现整个路径的拼接。

debug-builder-run

整个过程调用栈比较长,调试起来比较麻烦,知道这里将search-locations+label+name拼接起来就行(上面代码中447行中的locationsearch-locations+label的结果)。

debug-stack

load方法如下

debug-load

load方法调用loadForFileExtension方法,在其中发现整个文件路径的拼接

debug-loadForFileExtension

注意拼接后还带上了 "-" + profile + fileExtension,虽然profilefileExtension都是可控的,但是这个-比较难处理。-的存在会导致绝大部分文件都无法被读取。

注意到修复中将#做了限制,根据#在URL中的特性猜测#会使后面的字符变成标识符,不会被识别。

location-contain-sharp

构造PoC进行请求后发现果然能用#“注释”后面的内容。

复现

PoC:http://127.0.0.1:8888/test.txt%23/seikei/..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29..%28_%29tmp%28_%29

test.txt文件中的内容为just for test,可以看到其中存在多处文件信息回显。因为file:/tmp//test.txt#-seikei.xml#后面的字符不会被解析,等于访问的是file:/tmp//test.txt

poc1

由于整个文件路径是由labelname进行的拼接,所以也可以在name处输入路径回溯符。

测试之后发现同样会返回文件内容。

PoC2:http://127.0.0.1:8888/..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252F..%252Ftmp%252Ftest.txt%23/seikei/test

poc2

参考

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