环境:
https://github.com/shadowsock5/spring-cloud-config-starter
详细分析参考:
https://blog.riskivy.com/cve-2020-5405-spring-cloud-config-server-%e7%9b%ae%e5%bd%95%e7%a9%bf%e8%b6%8a/
启动完成:
curl -u root:root http://192.168.170.139:8888/cqq-config/test
修复的commit是这个:
https://github.com/spring-cloud/spring-cloud-config/commit/651f458919c40ef9a5e93e7d76bf98575910fad0
根据log里的报错,在org/springframework/cloud/config/server/resource/ResourceController#retrieve
下断点:
结合源码调试:
https://github.com/spring-cloud/spring-cloud-config
总结
1、/etc/hosts无法读取;/etc/hosts.allow可以读取;/etc/ca-certificates.conf还可通过拼接读取。
2、路径穿越可以被利用的条件是:
在配置文件application.properties/application.yml中配置spring.profiles.active的值为本地文件系统native(默认是git的url?);
3、没有后缀的文件(比如/etc/passwd)无法读取,因为有一个获取文件后缀名的逻辑,即便已经读到了文件内容但是由于没有后缀名出现异常然后响应500。
调试
在org/springframework/cloud/config/server/resource/ResourceController#retrieve
下断点就行了。
贴一下代码:
synchronized String retrieve(ServletWebRequest request, String name, String profile,
String label, String path, boolean resolvePlaceholders) throws IOException {
name = resolveName(name);
label = resolveLabel(label);
Resource resource = this.resourceRepository.findOne(name, profile, label, path);
if (checkNotModified(request, resource)) {
// Content was not modified. Just return.
return null;
}
// ensure InputStream will be closed to prevent file locks on Windows
try (InputStream is = resource.getInputStream()) {
String text = StreamUtils.copyToString(is, Charset.forName("UTF-8"));
String ext = StringUtils.getFilenameExtension(resource.getFilename())
.toLowerCase();
Environment environment = this.environmentRepository.findOne(name, profile,
label, false);
if (resolvePlaceholders) {
text = resolvePlaceholders(prepareEnvironment(environment), text);
}
if (encryptEnabled && plainTextEncryptEnabled) {
ResourceEncryptor re = this.resourceEncryptorMap.get(ext);
if (re == null) {
logger.warn("Cannot decrypt for extension " + ext);
}
else {
text = re.decrypt(text, environment);
}
}
return text;
}
}
org/springframework/cloud/config/server/resource/GenericResourceRepository#findOne
关键的判断文件后缀点逻辑:
(_)
->
/
转换:
org/springframework/cloud/config/server/resource/ResourceController.java
转换前:
转换后:
Demo
参考:
- CVE-2020-5405: Directory Traversal with spring-cloud-config-server
- 【漏洞通告】Spring-cloud-config-server路径遍历漏洞(CVE-2020-5405)通告
- https://www.baeldung.com/spring-cloud-configuration
- https://howtodoinjava.com/spring-cloud/spring-cloud-config-server-git/
- http://www.ityouknow.com/springcloud/2017/05/22/springcloud-config-git.html
- https://github.com/ityouknow/spring-cloud-examples/blob/master/spring-cloud-config-git/spring-cloud-config-server
- 通用的 HTTP 认证框架
- https://github.com/shadowsock5/spring-cloud-config-starter