CVE-2024-38816 Spring路径穿越漏洞分析复现
漏洞介绍
Spring Framework 是一个功能强大的 Java 应用程序框架,旨在提供高效且可扩展的开发环境。
2024年9月13日,监测到Spring Framework中修复了一个路径遍历漏洞(CVE-2024-38816),该漏洞的CVSS评分为7.5。
Spring Framework受影响版本中,使用WebMvc.fn 或 WebFlux.fn(在Spring Web MVC或Spring WebFlux框架中)提供静态资源的应用程序容易受到路径遍历攻击,当Web 应用程序使用RouterFunctions提供静态资源并且应用程序使用FileSystemResource或类似的配置来从文件系统提供静态文件时,威胁者可构造恶意HTTP请求访问目标文件系统上Spring 应用程序进程有权访问的任意文件,从而导致数据泄露。
影响范围
Spring Framework 5.3.0 - 5.3.39
Spring Framework 6.0.0 - 6.0.23
Spring Framework 6.1.0 - 6.1.12
以及不受支持的旧版本。
漏洞复现
payload
GET /static/%5c/%5c/../../a.txt HTTP/1.1
Host: 192.168.133.1:8081
成功读取到a.txt的内容。
漏洞分析
先看官方仓库的commit信息,啊apply函数中主要更改了下面的部分内容,原本是通过processPath处理过路径后然后Url解码,再用!StringUtils.hasLength(path) || isInvalidPath(path)对路径进行安全判断。在修改后没有先进行URL解码,在原本的检查后多了一个新的函数isInvalidEncodedInputPath又重新检查路径。最后判断了一下是否是UrlResource资源,不是的话才会进行URL解码,但是原本这里是都进行了URL解码。所以这里传入的如果是UrlResourece资源的话在旧版本中可能可以通过两次Url编码进行绕过后面的检查。
继续查看更新的内容,对processPath进行了更新,我觉得主要是这里对 \ 替换成了/ 其他没有太大改变。
新增加的这个函数中是对Url编码的数据增加了判断,先经过解码,然后通过isInvalidPath进行判断,和旧版逻辑一样,后面对数据又多了一部分判断,重新使用processPath函数进行处理后又调用isInvalidPath进行判断了。
最后增加的isResourceUnderLocation函数中主要还是对编码后的数据进行目录穿越判断。
总体看下来路径穿和url编码和\相关。其中几个关键的函数
org.springframework.web.reactive.function.server.PathResourceLookupFunction#processPath
就是去除多余的// 比如///////a.txt 处理后就变成了/a.txt
新版本中多了一个将 \ 替换成 / 并且中间多余的// 也替换成单个/ 比如 ///a//b.txt 变成俩 /a/b.txt
org.springframework.web.reactive.function.server.PathResourceLookupFunction#isInvalidPath
这个函数就是判断存不存在路径穿越,其中这个函数先是检查了几个禁止的目录信息比如WEB-INF等,后续又调用了
return path.contains("..") && StringUtils.cleanPath(path).contains("../");
这个函数在处理路径时比较又特点,比如传入的如果是/a/b/c/../../a.txt 返回的则是/a/a.txt,但是在处理///../../a.txt时候又存在问题,它会将//也当作是一个目录,所以后///../../a.txt变成了/a.txt,就满足了 StringUtils.cleanPath(path).contains("../") 为False,但是在文件系统中///../../a.txt会被认为是/../../a.txt。具体的可以参考CVE-2018-1271,经典老图。
所以我们只需要传入一个/////多个连续的传入cleanPath就可以配合../实现路径穿越。但是在执行过程的前面存在processPath函数处理了多级//// 都被替换成一个/符号。新版中在processPath中增加了将\替换成/所以明显和\相关。在查看cleanPath函数的实现过程可以看到将\替换成了/所以我们只需要传入一个//这样的既不会被cleanPath给处理成一个/也可以在cleanPath中被处理成 \ \ \ \ 继续执行。
所以构造一个 static/%5c/%5c/../../a.txt 进行调试。
在org.springframework.web.reactive.function.server.PathResourceLookupFunction#apply打下断点。
可以看到这里processPath函数并未处理掉%5c (\) 在后续又会将path进行url解码替换成 /
然后后续继续调用到了isInvalidPath 函数,可以看到在path 传入到cleanPath后返回的结果不包含../ 成功绕过检测。
然后退出函数继续调用了createRelative创建资源。在createRelative中调用了FileSystemResource函数,其中虽然this.path是通过cleanPath处理后端路径,但是这里创建File对象时候也是使用了传入的参数path (E:/tmp///../../a.txt)然后filePath变成了 (E:\ tmp\ ..\ ..\ a.txt)实现了目录穿越
后续又调用了isResourceUnderLocation 判断,最后调用了Mono.just(resource)结束。读取到文件。
总体分析的差不多,参考了一些大佬的其他文章,有错误欢迎指出。其中能触发漏洞环境的也不一定非要是FileSystemResource 类型的,也可以是其他类型的比如:UrlResource
resources("/static/**", new UrlResource(new URL("file:E:/tmp/")));
参考链接:
Align RouterFunctions resource handling · spring-projects/spring-framework@d86bf8b (github.com)
vulhub中Nexus Repository Manager 3 未授权目录穿越漏洞(CVE-2024-4956)-CSDN博客
【漏洞通告】Spring Framework路径遍历漏洞(CVE-2024-38816)-启明星辰 (venustech.com.cn)