转载

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

在 这里 先生成spring工程。

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

然后修改 pom.xml ,引入 spring cloud config 依赖。

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>

新建一个 ConfigServerApplication.java 文件,导入下面的代码

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;


@EnableConfigServer
@EnableAutoConfiguration
@SpringBootApplication

public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}

配置 application.properties 文件,增加端口以及 giturl

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

0x03 漏洞分析

Spring Cloud Config是 Spirng Cloud 下用于分布式配置管理的组件,分为 Config-ServerConfig-Client 两个角色。 Config-Server 负责集中存储/管理配置文件, Config-Client 则可以从 Config-Server 提供的HTTP接口获取配置文件使用。首先看一下路由请求,代码在 spring-cloud-config-server-2.0.2.RELEASE.jar!/org/springframework/cloud/config/server/resource/ResourceController.class

@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);
}

也就是说我们可以通过请求 GET /{name}/{profile}/{label}/{path} 来获取配置文件,这里 name 为应仓库名称, profile 为应配置文件环境, label 为git分支名。实际测试中需要 label 为存在的分支名(一般git仓库都存在master分支),否则报错,name和profile可以为任意。所以我们构造如下payload即可命中这个 RequestMapping

http://127.0.0.1:8888/aaa/bbb/master/{payload}

这里在path打一个断点,单步跟入一下,我们发现 path 为我们传入的 payload ,且已经经过了一次 urldecode

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

跟进一下 retrieve 方法,位置在

org/springframework/cloud/config/server/resource/ResourceController.class:79

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

再跟进一下 findOne 方法,位置在

org/springframework/cloud/config/server/resource/GenericResourceRepository.class:31

这里我在 file.exists() && file.isReadable() 这里下一个断点,可以看到 locations 的值是一个临时文件夹

file:/var/folders/f0/pg_5gh954xl9r26dq3p0dxgc0000gn/T/config-repo-1558519048781287859/

local 的值就是我们传入的 payload

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

进入这个临时文件夹看看,这里我们配置的git目录的内容,被它拉取了一份到临时文件夹下。

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

最后return的时候,自然将路径拼接在一起。

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

然后返回到了 retrieve 方法中,调用了 StreamUtils.copyToString 方法读取我们传入的文件路径,并且输出。

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

0x04 漏洞修复

漏洞修复代码位置

主要是针对了我们在之前在 local 传入的 payload 位置进行了处理,处理方法是 isInvalidPathisInvalidEncodedPath

if (!isInvalidPath(local) && !isInvalidEncodedPath(local)) {
Resource file = this.resourceLoader.getResource(location)
.createRelative(local);
if (file.exists() && file.isReadable()) {
return file;
}

主要还是对 :/..WEB-INF 等关键字样进行检测。

protected boolean isInvalidPath(String path) {
if (path.contains("WEB-INF") || path.contains("META-INF")) {
if (logger.isWarnEnabled()) {
logger.warn("Path with /"WEB-INF/" or /"META-INF/": [" + path + "]");
}
return true;
}
if (path.contains(":/")) {
...
if (path.contains("..") && StringUtils.cleanPath(path).contains("../")) {
if (logger.isWarnEnabled()) {
logger.warn("Path contains /"..//" after call to StringUtils#cleanPath: [" + path + "]");
}
return true;
}
return false;
}
原文  http://www.lmxspace.com/2019/04/26/Spring-Cloud-Config-Server-任意文件读取分析/
正文到此结束
Loading...