转载

CVE-2020-5405 Spring Cloud Config Server 目录穿越

事件背景

Spring Cloud Config为分布式系统的外部配置提供客户端的服务端的支持。使用了它,开发人员就可以在一个中心仓库管理应用程序在所有环境中的外部配置。2020-02-26 Spring 收到漏洞报告, Spring Cloud Config Server 存在目录穿越漏洞。

时间线

2020-02-26 Spring 收到漏洞报告, Spring Cloud Config Server 存在目录穿越漏洞

2020-03-03 Spring Cloud Config Server 更新 2.1.7 版本

2020-03-04 Spring Cloud Config Server 更新 2.2.2 版本

2020-03-06 斗象应急响应团队分析出漏洞POC

漏洞挖掘

根据描述该漏洞为目录穿越 2.2.0-2.2.1,2.1.0-2.1.6 都受到影响, 所以这里直接下载2.2.1和2.2.2的源码包进行对比

https://github.com/spring-cloud/spring-cloud-config/releases

解压后直接使用idea Ctrl+D 进行对比

CVE-2020-5405 Spring Cloud Config Server 目录穿越

很多开源项目都会在test文件中写入本次更新涉及的漏洞点

比如这次  spring-cloud-config-2.2.2.RELEASE/spring-cloud-config-client/src/test/java/org/springframework/cloud/config/environment/EnvironmentTests.java

CVE-2020-5405 Spring Cloud Config Server 目录穿越

显而易见的这个漏洞是用 (_) 来代替  / 进行目录穿越

搭建环境

这里启动 2.2.1环境, 使用idea 打开 (maven项目)

/spring-cloud-config-2.2.1.RELEASE/spring-cloud-config-server

这里如果速度慢可以修改成阿里源,启动成功后访问

http://127.0.0.1:8888/foo/default/master/test.json

CVE-2020-5405 Spring Cloud Config Server 目录穿越

补丁对比

根据上一个目录穿越漏洞

Spring Cloud Config Server 路径穿越与任意文件读取漏洞分析 – 【CVE-2019-3799】 – 先知社区

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

这里可以构造一个路径进行尝试(看看报错)

/foo/default/master/..(_)..(_)..(_)..(_)etc(_)passwd
CVE-2020-5405 Spring Cloud Config Server 目录穿越

效果不佳,从文中可知请求格式如下

GET /{name}/{profile}/{label}/{path}

继续看对应实现源码

org/springframework/cloud/config/server/resource/ResourceController.java

CVE-2020-5405 Spring Cloud Config Server 目录穿越

这里可以知道请求的格式,这里决定了POC的基本结构

继续对比可以可以看出, (_) 会在 [ name / label ] 时被处理成  /
CVE-2020-5405 Spring Cloud Config Server 目录穿越

再根据新增的测试文件

spring-cloud-config-2.2.2.RELEASE/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/resource/GenericResourceRepositoryTests.java

CVE-2020-5405 Spring Cloud Config Server 目录穿越

基本可以构造出来如下格式

CVE-2020-5405 Spring Cloud Config Server 目录穿越
由于label中可以解析 (_)
CVE-2020-5405 Spring Cloud Config Server 目录穿越

根据提示 “Cannot clone or checkout repository” 以及 代码中的

this.nativeRepository.setSearchLocations("file:./src/test/resources/test/local");

这里考虑可能是得采用本地配置文件方式

玩转Spring Cloud之配置中心(config server &config client) – 梦在旅途 – 博客园

https://www.cnblogs.com/zuowj/p/10432445.html

更改配置文件为

configserver.yml

info:
  component: Config Server
spring:
  application:
    name: configserver
  autoconfigure.exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
  profiles:
    active: native
  jmx:
    default_domain: cloud.config.server
  cloud:
    config:
      server:
        #如下是本地文件配置
        native:
          search-locations: classpath:/configs #配置文件存放的目录

server:
  port: 8888
management:
  context_path: /admin

然后再resources目录下新建文件夹 configs

随便放个配置文件

configclient-dev.properties

--configclient-dev.properties内容:

demo-config-profile-env=dev-native
zuowenjun.site=http://www.zuowenjun.cn,http://zuowj.cnblogs.com--20190227
zuowenjun.skills=.net,java,html,js,css,sql,python,vb--20190227
zuowenjun.motto=Learning is endless; Opportunity is for the prepared mind;--20190227

访问 http://127.0.0.1:8888/configclient/dev

CVE-2020-5405 Spring Cloud Config Server 目录穿越

当native本地方式启动时, {label}无需指定(有用但是对这个漏洞没有影响), 所以这里可以采取{label}可以生效的方式git后端配置的请求格式进行访问

Spring Cloud Config Server 启动后, GIT仓库中的配置文件会被自动转换成当前项目的web api,若需访问查看远程配置数据可以参照以下的规则:
/{application}/{profile}[/{label}]
[/{label}]/{application}-{profile}{.yml|.properties|.json}

规则简单说明:{application}=配置消费方应用名称(即:config client的项目名,通俗讲:就是谁用这个配置就是谁的名字)

{profile}=配置环境(如:dev开发环境,test测试环境,prod生产环境)

{label}=仓库分支名(git或svn方式指定,native本地方式无需指定)

.yml|.properties|.json表示指定的响应返回格式,{}表示必需,[]表示可选,|表示或的关系

或者参考

https://cloud.spring.io/spring-cloud-static/spring-cloud-config/2.2.2.RELEASE/reference/html/#_placeholders_in_git_uri


https://www.cnblogs.com/zuowj/p/10432445.html

CVE-2020-5405 Spring Cloud Config Server 目录穿越

当配置文件中的 search-locations 修改为 file:///c:/ 时,即可在在根目录进行文件读取

configserver.yml

info:
  component: Config Server
spring:
  application:
    name: configserver
  autoconfigure.exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
  jmx:
    default_domain: cloud.config.server
  profiles:
    active: native
  cloud:
    config:
      server:
        native:
          search-locations: file:///C:/TCC/Spring-cloud-config-server/spring-cloud-config-2.2.1.RELEASE/spring-cloud-config-server/src/main/resources/configs #配置文件存放的目录
server:
  port: 8888
management:
  context_path: /admin

CVE-2020-5405 Spring Cloud Config Server 目录穿越

断点分析

通过打断点,我们可以更清晰的看到漏洞的成因

首先根据路由格式,进入 org.springframework.cloud.config.server.resource.ResourceController#retrieve(java.lang.String, java.lang.String, java.lang.String, org.springframework.web.context.request.ServletWebRequest, boolean) 函数中

CVE-2020-5405 Spring Cloud Config Server 目录穿越

其中参数分别为我们传入的

name = blah

profile = local

label = 马赛克

path = Windows/win.ini

然后进入 org.springframework.cloud.config.server.resource.GenericResourceRepository#findOne 函数

CVE-2020-5405 Spring Cloud Config Server 目录穿越 CVE-2020-5405 Spring Cloud Config Server 目录穿越

这里会对 Win[-{label}].ini 也就是  win-label.ini win.ini 在对应目录搜索,

也就是 {search-locations} + {label}

file:///C:/TCC/Spring-cloud-config-server/spring-cloud-config-2.2.1.RELEASE/spring-cloud-config-server/src/main/resources/configs/../../../../../../../../../../../../../../../../../../../../../../../../../../../../..//

CVE-2020-5405 Spring Cloud Config Server 目录穿越

也就是进入了C盘根目录, 即可读取文件

无后缀文件读取

但是因为 org.springframework.cloud.config.server.resource.ResourceController#retrieve(org.springframework.web.context.request.ServletWebRequest, java.lang.String, java.lang.String, java.lang.String, java.lang.String, boolean) 中存在对于后缀的匹配导致没有后缀的文件会读取失败

CVE-2020-5405 Spring Cloud Config Server 目录穿越

46 对应ascii码的 .
CVE-2020-5405 Spring Cloud Config Server 目录穿越

当没有获取到 “.” 的时候返回 null 导致后续 null.toLowerCase() 报错异常退出

但是在windows中.当文件名后面加空格或者点号 . 也可以正确处理

Naming Files, Paths, and Namespaces – Win32 apps | Microsoft Docs

https://docs.microsoft.com/zh-cn/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN
Do not end a file or directory name with a space or a period. Although the underlying file system may support such names, the Windows shell and user interface does not. However, it is acceptable to specify a period as the first character of a name. For example, ".temp".

所以在Windows中,我们可以使用文件名加点 . 的方式进行无后缀文件读取

CVE-2020-5405 Spring Cloud Config Server 目录穿越

漏洞产生根本原因

org.springframework.cloud.config.server.environment.NativeEnvironmentRepository#getLocations
这里产生了直接拼接{label}的行为

CVE-2020-5405 Spring Cloud Config Server 目录穿越

所以这里双重url编码 /%252f 还是可以用,因为最后拼接成的路径是URL类,支持 %2f

CVE-2020-5405 Spring Cloud Config Server 目录穿越

使用  %252f 请求

CVE-2020-5405 Spring Cloud Config Server 目录穿越

Spring修复方式

修复点在

spring-cloud-config-2.2.2.RELEASE/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/resource/GenericResourceRepository.java

org.springframework.cloud.config.server.resource.GenericResourceRepository#findOne 函数加入了对路径的判断

CVE-2020-5405 Spring Cloud Config Server 目录穿越

org.springframework.cloud.config.server.resource.GenericResourceRepository#isInvalidEncodedLocation 会先对路径进行url解码

CVE-2020-5405 Spring Cloud Config Server 目录穿越

org.springframework.cloud.config.server.resource.GenericResourceRepository#isInvalidLocation 然后检测是否包含  ..
CVE-2020-5405 Spring Cloud Config Server 目录穿越

原文  https://www.freebuf.com/news/232744.html
正文到此结束
Loading...