Spring 相关CVE分析复现

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框架有什么组件使用这个做底层进行匹配的话,可能也会存在绕过现象

posted @ 2024-11-07 17:32  Ch3nry  阅读(26)  评论(0)    收藏  举报