问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
CVE-2024-38821-Spring Security 静态资源权限绕过漏洞分析复现
漏洞分析
Spring官方发布了CVE-2024-38821,当WebFlux使用Spring的静态资源支持时,在特定情况下会存在权限绕过的风险。
0x00 漏洞简介 =========  0x01 影响版本 ========= Spring Security 版本: - 5.7.0 - 5.7.12 - 5.8.0 - 5.8.14 - 6.0.0 - 6.0.12 - 6.1.0 - 6.1.10 - 6.2.0 - 6.2.6 - 6.3.0 - 6.3.3 - Older, unsupported versions are also affected 0x02 漏洞原理分析 =========== `@EnableWebFluxSecurity` 是 Spring Security 提供的一个注解,用于在 Spring WebFlux 应用程序中启用 Spring Security 功能。这个注解会激活 Spring Security 的 WebFlux 支持,允许你定义安全配置,比如认证、授权、CSRF 保护等。 而pathMatchers() 方法用于指定哪些路径需要被特定的安全配置所应用,可以通过该方法来设置哪些路径应该被认证、哪些路径可以公开访问等。例如下面的例子: ```Java @Bean public SecurityWebFilterChain securityWebFilterChain(final ServerHttpSecurity http) { return http .csrf().disable() .authorizeExchange().matchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() .pathMatchers(HttpMethod.GET, "/portal/*.log").hasAuthority("ADMIN") .anyExchange().permitAll() .and() .formLogin() .loginPage("/login") .and() .logout() .logoutUrl("/logout") .requiresLogout(ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, "/logout")) .and() .build(); } ``` WebFlux.fn 是 Spring WebFlux 中提供的一种轻量级的函数式编程模型,它允许开发者使用函数来处理 HTTP 请求和响应。这个模型特别适合与响应式编程范式一起使用,提供了一种声明性和非阻塞的方式来处理 Web 请求。 &emsp 在 WebFlux.fn 中,HTTP 请求由 HandlerFunction 处理,这是一个接受 ServerRequest 并返回延迟的 ServerResponse(即 Mono\\)的函数。 漏洞的成因主要是WebFlux.fn静态资源解析在特定情况下与pathMatchers的匹配存在解析差异,从而导致了权限绕过的风险。下面是具体的分析: 2.1 pathMatchers解析过程 -------------------- 在SpringSecurity中,对于Spring WebFlux,会使用`pathMatchers`来实现基于请求路径进行权限配置的功能。 pathMatchers的匹配主要跟PathPatternParserServerWebExchangeMatcher有关:  首先根据用户配置创建基于路径匹配的 `ServerWebExchangeMatcher` 对象。创建一个空的 `matchers` 列表,用于存储创建的 `PathPatternParserServerWebExchangeMatcher` 对象。匹配请求路径的功能是由 PathPatterParserServerWebExchangeMatcher 来实现的。其会拦截请求路径,并且提取请求路径的参数。遍历传入的 `patterns` 数组,并对于每个路径模式,创建一个 `PathPatternParserServerWebExchangeMatcher` 对象,并传入该模式和请求方法,然后添加到`matchers` 列表中:  查看`PathPatternParserServerWebExchangeMatcher`的实例化过程,其中传入的pattern属性会调用parse方法进行处理,在parse方法中调用了initFullPathPattern进行处理,对不是以`/`开头的情况进行补全(修复CVE-2023-34034):   然后调用`org.springframework.web.util.pattern.InternalPathPatternParser#parser`进行处理:  在parse方法中,首先遍历路径模式字符串的每个字符,在遍历过程中,首先检查是否遇到路径分隔符(`separator`),如果是,则创建对应的 `SeparatorPathElement` 或 `WildcardTheRestPathElement` 并添加到解析结果中:  再者是对一些特殊字符的处理,主要包括`?{}:*`,以`:` 字符为例,其表示变量捕获的正则表达式结束,会进行相应的状态更新:  如果处于变量捕获状态,则根据规则检查字符的合法性,并抛出对应的异常:  遍历完成后,将最后一个路径元素添加到解析结果中。并使用解析得到的路径模式字符串、解析器和解析结果创建并返回 `PathPattern` 对象,用于后续的路径匹配和处理:  当请求对应的path时,Spring Security会遍历前面封装好的安全配置,进行匹配:  而PathPatternParserServerWebExchangeMatcher的matches方法主要用来用来判断请求是否匹配。**实际上使用的PathPattern模式进行解析**。具体解析模式的分析可以参考:<https://forum.butian.net/share/2214> 一开始exchange使用 `getRequest()` 方法获取 `ServerHttpRequest` 对象,然后再通过`getPath()` 方法获取请求路径,然后获取当前请求的方法,判断请求方法与当前规则是否一致:  如果请求方法匹配或者没有指定请求方法,会调用 `PathPattern` 对象的 `matches` 方法,将当前请求的路径和请求方法传递给路径模式对象,进行路径匹配判断,如果匹配失败,则返回一个不匹配的结果,并在日志中记录对应的信息:  如果路径匹配成功,则使用当前的路径模式 (`pattern`) 提取路径变量,并将路径变量保存在 `pathVariables` 中:  最终返回匹配的结果供后续权限校验使用。 2.2 WebFlux.fn静态资源解析过程 ---------------------- PathResourceLookupFunction在响应式路由中处理静态资源请求。将请求的路径映射到文件系统中的资源,如图片、样式表或 JavaScript 文件等。以spring-webflux-5.3.29为例,查看具体的解析过程。 在解析时主要调用的是org.springframework.web.reactive.function.server.PathResourceLookupFunction#apply方法进行处理:  若原始请求路径中包含`%`时,会进行一次URL解码:  然后会调用isInvalidPath进行一些安全检查: - 检查路径字符串 `path` 是否包含 `WEB-INF` 或 `META-INF` - 使用 ResourceUtils.isUrl(relativePath) 检查相对路径是否是一个有效的 URL(类似classpath:的调用)。如果是,或者路径以 url: 开头,表明这是一个指向外部资源的路径。也是不合理的 - 检查路径中是否包含 `..`,这可能是尝试进行路径遍历的尝试。通过 `StringUtils.cleanPath(path)` 处理路径后会再次检查是否包含 `../`  `StringUtils.cleanPath`中,会对路径中的`../`进行处理,例如`/admin/../test.log`在处理后`../`会跟之前的目录进行抵消: ```Java String path = "/admin/../test.log"; System.out.println(StringUtils.cleanPath(path)); ```  然后会通过this.location.createRelative(path) 创建一个 Resource 对象,这个对象代表了请求的资源。然后检查创建的资源是否可读,并且是否位于定义的资源位置下:  createRelative主要是实例化了org.springframework.core.io.FileUrlResource:  实际是封装成了java.net.URL对象:  在解析时会通过org.springframework.core.io.UrlResource#getInputStream方法来获取对应的资源,这里会再对请求路径解码一层:  熟悉PathPattern的话,其在解析`../`会当成一个目录进行处理,不会进行额外的目录回溯,通过仅支持一层URL的解码操作,也就是说,相比pathMatchers的解析,WebFlux.fn在进行静态资源解析时还额外支持如下解析: - 支持`../`的目录回溯 - 通过File协议请求资源时支持URL双重解码 正是这些差异导致了相关的Bypass。下面是具体的复现过程: 0x03 环境搭建 ========= SpringSecurity配置如下,对于portal路径下的所有log后缀结尾的内容,均需要ADMIN权限才可以访问:  WebFlux.fn注册的静态路由映射如下,将/tmp目录的内容通过/portal路由进行访问:  当尝试访问portal下的test.log内容时,因为缺少ADMIN权限返回302 status:  0x04 漏洞复现 ========= 基于前面的分析,下面列举一些可能的绕过方式(由于**CVE-2024-38816&CVE-2024-38819**的修复,部分绕过方式可能受版本限制): **绕过方式一**: 正如前面的分析,类似`/admin/../test.log`的请求会进行目录回溯,同时不影响相关的安全检查,但是在SpringSecurity解析时会认为`../`是额外的目录节奏,从而绕过了`/portal/*.log`的鉴权配置:  在修复**CVE-2024-3881**9时,在调用processPath时增加了normalizePath的处理:  normalizePath中对`../`进行了处理:  包括isInvalidPath也进行了修改,最后只判断path中是否包含`../`,避免了类似方式一种`/admin/../test.log`经过之前`cleanPath`方法转换后变成`test.log`导致误认为path合法的情况:  并且在最后isResourceUnderLocation方法处理时考虑了双重url编码以及`../`的问题,所以高版本默认情况下是无法通过方式一进行绕过的:  0x05 其他 ======= 因为具体的匹配方式是`/portal/*.log`,即使高版本对方式一进行了处理,仍可以利用File协议解码的特点,通过双重URL编码的方式,绕过对应的权限检查:  5.1 为什么Spring WebMvc.fn不受影响 --------------------------- `WebMvc.fn` 是 Spring Web MVC 的一部分,它提供了一种轻量级的函数式编程模型,允许开发者使用函数来定义路由和处理 HTTP 请求。这种模型是注解编程模型的替代方案。 在 `WebMvc.fn` 中,HTTP 请求由 `HandlerFunction` 处理,这是一个接收 `ServerRequest` 并返回 `ServerResponse` 的函数。一般可以通过RouterFunctions.route()方法进行处理。同样的也支持File协议的静态资源映射,在解析过程中也进行了相应的URL解码处理:  但是实际上当使用SpringSecurity进行防护时,利用双重URL编码的方式并不能很好的绕过对应的安全防护。原因是因为org.springframework.security.web.firewall.StrictHttpFirewall默认场景下对请求中的非法字符进行了拦截处理:  但是因为整体逻辑是基于serlvet/filter实现的,WebFlux并不适用,所以没办法进行覆盖。 5.2 修复方式 -------- Spring官方的修复方式也很简单,主要是基于WebFlux的场景,在SpringSecurity中新增了org.springframework.security.web.server.firewall.StrictServerWebExchangeFirewall,对请求过程中的一些恶意字符进行了处理:  也包括在前面复现场景中看到的的`../`以及对应的URL编码等: 
发表于 2024-10-29 10:07:18
阅读 ( 8491 )
分类:
开发框架
3 推荐
收藏
1 条评论
wan9x
1秒前
复现漏洞的源码可以分享一下吗,谢谢师傅
请先
登录
后评论
请先
登录
后评论
tkswifty
2 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!