其他
浅谈SpringSecurity与CVE-2023-22602
点击蓝字
关注我们
前言
相关原理
protected void configure(HttpSecurity httpSecurity) throws Exception{
httpSecurity.authorizeRequests().antMatchers("/admin/*").authenticated();
}
2.1 AntPathRequestMatcher
/**
的话,说明是全路径匹配返回true。否则获取当前请求的url,然后调用当前matcher的matches方法进行进一步的匹配:/**
结尾并且不包含路径变量(即通配符{}),会使用SubpathMatcher,否则 matcher 赋值为 SpringAntMatcher 类的对象。SubpathMatcher
/admin/**
,此时会使用SubpathMacher#matches进行解析。具体实现如下:/
则返回ture(满足/admin或者/admin/目录的访问方式):SpringAntMatcher
/admin/*
为例,首先会调用getStringMatcher方法:*
最后会变成.*
:2.2 PathPattern
//
处理成/
,也没有处理路径穿越。例如Pattern的第一个元素为/的话,会调用SeparatorPathElement的matches方法进行处理,结束后pathIndex++,继续遍历下一个元素进行处理:
WildcardPathElement(/api/*) SingleCharWildcardedPathElement(/api/?) WildcardTheRestPathElement(/api/**) CaptureVariablePathElement(/api/{param}) CaptureTheRestPathElement(/api/{*param}) LiteralPathElement(/api/index) RegexPathElement(/api/.*)
绕过场景
3.1 java.util.regex.Pattern模式差异
spring-core-5.3.21
spring-core-5.3.22
.
匹配任何字符,包括行结束符。protected void configure(HttpSecurity httpSecurity) throws Exception{
httpSecurity.authorizeRequests().antMatchers("/admin/*").authenticated();
}
访问的Controller如下:
@GetMapping("/admin/*")
public String Manage(){
return "manage";
}
/admin/page%0a
会失败,然后转由Spring的PathPattern进行解析,首先是admin字符匹配,当解析到*
时会使用WildcardPathElement进行解析,若没有下一个Element元素的话,只要pathElements的元素个数和PathPattern中的元素个数一致都会返回true,也就是说page%0a跟*
是可以成功匹配的:.
匹配任何字符,包括行结束符,无法auth Bypass:@GetMapping("/admin/{param}")
public String Manage(){
/*return "Manage page";*/
return "manage";
}
{param}
时,PathPattern会使用CaptureVariablePathElement进行处理,因为通配符{}中没有正则,所以这里只需要pathElements的元素个数和PathPattern中的元素个数一致都会返回true:低版本的Spring使用的是AntPathMatcher,即使绕过了SpringSecurity也会因为解析差异找不到对应的Controller返回404。 SpringSecurity高版本的StrictHttpFirewall对\r或者\n(\r的URl编码为%0d,\n的URL编码为%0a)进行了拦截处理:
3.2 请求Path归一化差异
/admin/..
最终会处理为/
:@Override
protected void configure(HttpSecurity httpSecurity) throws Exception{
httpSecurity.authorizeRequests().antMatchers("/admin/*").authenticated();
}
@GetMapping("/admin/*")
public String Manage(){
return "manage";
}
/admin/..
时,AntPathRequestMatcher在处理时会认为当前请求的path是/
,在进行匹配的时候因为请求的path为/
,在isPotentialMatch方法处理时会认为没有潜在匹配的可能返回false:..
跟*
是可以成功匹配的。@Override
protected void configure(HttpSecurity httpSecurity) throws Exception{
httpSecurity.authorizeRequests().antMatchers("/admin/**").authenticated();
}
@GetMapping("/admin/**")
public String Manage(){
return "manage";
}
/**
结尾并且不包含路径变量(即通配符{}),会使用SubpathMatcher。匹配逻辑也比较简单,若请求的path以subpath开头,并且path的长度等于subpath的长度或者subpath长度后第一个字符是/
则返回ture(满足/admin或者/admin/目录的访问方式)。这里/
跟/admin
以及/admin/
明显是不匹配的。..
是可以匹配上/**
的,同样的由于SpringSecurity不能解析但是Spring Framework的PathPattern可以解析导致了Auth Bypass问题。其他
往期推荐