CVE-2022-22978 Spring Security RegexRequestMatcher 认证绕过及转发流程分析
字数 1614 2025-08-27 12:33:37
Spring Security RegexRequestMatcher 认证绕过漏洞分析(CVE-2022-22978)
漏洞概述
CVE-2022-22978是Spring Security中RegexRequestMatcher组件的一个认证绕过漏洞,由于正则表达式处理特性导致某些需要认证的Servlet可能被绕过。影响版本包括:
- 5.5.x prior to 5.5.7
- 5.6.x prior to 5.6.4
- Earlier unsupported versions
漏洞成因
漏洞核心在于正则表达式.默认不会匹配换行符,攻击者可以在URL中加入换行符(\r或\n)来绕过正则表达式匹配。
补丁中新增了Pattern.DOTALL模式(0x20),该模式下表达式.会匹配任何字符包括行终止符。开发者也可以通过嵌入标志表达式(?s)启用Dotall模式。
环境搭建
使用Spring Boot 2.7.0和Spring Security 5.6.3版本进行测试:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
</parent>
<properties>
<spring-security.version>5.6.3</spring-security.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
安全配置类示例:
@Configuration
public class SecurityDemo extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests()
.regexMatchers("/admin/.*", "/admin2").authenticated();
}
}
漏洞分析
关键调试点
-
正则匹配过程:
- 进入
org.springframework.security.web.util.matcher.RegexRequestMatcher#matches方法 request.getServletPath()会对字符解码并删除;之后的字符到/字符request.getRequestURI()会原样输出
- 进入
-
Spring Boot 2.7.0的请求处理流程:
- 从过滤器出来后,分发器(Dispatcher)选择相应处理器
org.springframework.web.servlet.DispatcherServlet#getHandler方法处理映射RequestMappingInfoHandlerMapping继承AbstractHandlerMethodMapping- 虽然会移除分号,但在Spring Security前面就会被过滤
-
Spring Boot 2.5.3的区别:
lookupPath会将%0a解码,导致映射不到对应路由- 进入
org.springframework.web.util.UrlPathHelper#decodeAndCleanUriString - 在
decodeRequestString处将URL解码返回,导致路由映射失败
路由匹配机制
- 首先从
directPath中寻找匹配 - 然后匹配带有通配符的path
- 最终匹配使用的是
request对象 org.springframework.util.AntPathMatcher#doMatch方法使用与RegexRequestMatcher相同的Pattern模式(flag为0),导致\n字符无法被匹配
绕过示例
基本绕过
在URL中加入换行符:
/admin/%0a
带参数的绕过
@RestController
public class NewController {
@GetMapping("/admin2")
public String noatuh(){
return "hello admin2";
}
}
参数拼接后与需要校验认证的路径进行对比时可能导致认证绕过。
修复方案
官方修复
升级到安全版本:
- Spring Security 5.5.7+
- Spring Security 5.6.4+
代码层面修复
在路径匹配中使用单行模式((?s)):
@Configuration
public class SecurityDemo extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests()
.regexMatchers("/admin/(?s).*", "/admin2").authenticated();
}
}
技术要点总结
-
正则表达式模式:
- 默认
.不匹配换行符 Pattern.DOTALL或(?s)启用单行模式
- 默认
-
请求处理差异:
- 不同Spring Boot版本对URL解码处理不同
- 高版本(2.7.0)能正确映射,低版本(2.5.3)会因解码导致404
-
安全防护:
StrictHttpFirewall默认会过滤特殊字符- 但攻击者仍可能通过编码方式绕过
-
路由匹配优先级:
- 先匹配
directPath - 再匹配通配符path
- 最终使用
request对象匹配
- 先匹配
通过深入理解这些机制,可以更好地防御类似的安全漏洞。