Spring Security
相关的鉴权绕过
CVE-2022-22978
成因
HttpSecurity
路由鉴权模块中采用regexMatchers
进行匹配,而regexMatchers
中正则匹配不会去匹配\r\n
导致绕过
影响版本
Spring Security 5.4.x < 5.4.11
Spring Security 5.5.x < 5.5.7
Spring Security 5.6.x < 5.6.4
漏洞代码
1.第一个前提
.regexMatchers("/admin/.*").authenticated()
2.是Mapping中写法需要匹配全路径
@GetMapping("/admin/**")
@GetMapping("/admin/123") //这样指定了具体路由的不行
public String Bye(){
return "OKKK";
}
绕过
- 通过
/admin/%0D
或者/admin/%0A
,/admin
等进行绕过 - 不过这个绕过之后只能返回
**
中的路由返回的,其他具体路由都不行,其实实战没啥用
具体分析
- 因为这里用了正则匹配,而
JAVA
中的正则匹配会使用Pattern
类定义规则,Matcher
类进行匹配,而此版本下的正则采用默认的匹配规则模式,导致无法匹配\n
和\r
,从而绕过 - 可以看到该版本下,只有一个对于大小写的可选模式
- 而官方的修复就是匹配规则多采用一个
Pattern.DOTALL
模式即可匹配回车换行符,可以看到5.6.4
修复如下
测试代码
Pattern pattern = Pattern.compile("a.*b");
System.out.println(pattern.matcher("aaabbbb").matches()); //true
System.out.println(pattern.matcher("aaab\rbbb").matches()); //false
Pattern pattern1 = Pattern.compile("a.*b",Pattern.DOTALL);
System.out.println(pattern1.matcher("aaabbbb").matches()); //true
System.out.println(pattern1.matcher("aaab\nbbb").matches()); //true
此外在Go
中也有这个现象,不过只是没法匹配\n
,\r
是可以的
pattern := regexp.MustCompile("a.*b")
fmt.Println(pattern.MatchString("aaabbbb")) //true
fmt.Println(pattern.MatchString("aaa\rbb")) //true
fmt.Println(pattern.MatchString("aaa\nbbb")) //false
pattern = regexp.MustCompile("(?s)a.*b")
fmt.Println(pattern.MatchString("aaa\nbbb")) //true
如果Go
框架有什么组件使用这个做底层进行匹配的话,可能也会存在绕过现象