SpringSecurity(CVE-2022-22978)权限校验分析

date
Jun 8, 2022
slug
SpringSecurity-CVE-2022-22978
status
Published
tags
Java安全
安全研究
summary
关于SpringSecurity权限校验的一个洞,可以拿来当一个trick之类的吧,之前没整过SpringSecurity,自己搭建一次熟悉一下,影响了5.5.7 之前的 5.5.x5.6.4 之前的 5.6.x早期不支持的版本
type
Post
 
关于SpringSecurity权限校验的一个洞,可以拿来当一个trick之类的吧,之前没整过SpringSecurity,自己搭建一次熟悉一下,影响了5.5.7 之前的 5.5.x 5.6.4 之前的 5.6.x早期不支持的版本
漏洞公告上说是RegexRequestMatcher这个东西出了问题
然后看github上的diff,发现只修了一个文件,然后添加了两个测试案例,根据上一次Spring Cloud Function RCE 的调试经验来看,这个test案例里面内容就是绕过检测的测试样例了,使用了%0a或者%0d进行绕过
notion image
 

搭建环境 && 复现

新建一个Springboot项目,然后在pom文件中引入SpringSecurity
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
 </dependency>
将SpringSecurity版本切换至5.6.3版本
notion image
创建controller
notion image
使用SpringSecurity设置相关权限,这个跟Shiro的Relam有点像,但是这里我们需要继承WebSecurityConfigurerAdapter 并实现其中的configure 方法
notion image
这里使用了正则去匹配admin路由下的内容,涉及到的函数:
http.authorizeRequests():主要是对url进行访问权限控制,通过这个方法来实现url授权操作。 authenticated():是访问控制方法的一种,表示所匹配的URL都需要被认证才能访问
此时授权与未授权的接口访问是不一样的
notion image
根据单元测试里面的payload,在路由最后添加上%0a或者%0d就能够绕过了
notion image
 

修复分析

观察修复内容,在RegexRequestMatcher.java文件的修复是增加了对换行符的匹配以及忽略大小写
Pattern.DOTALL:表示更改.的含义,使它与每一个字符匹配(包括换行符\n),默认情况下, 正则表达式中点(.)不会匹配换行符, 设置了Pattern.DOTALL模式, 才会匹配所有字符包括换行符。 Pattern.CASE_INSENSITIVE:忽略大小写。
写个测试样例看一下,可以观察到Pattern.DOTALL 模式下是直接给忽略掉了中间匹配的内容,最后导致并没有匹配输出,这也是导致bypass的本质原因,而Pattern.DOTALL 就能正常匹配内容了,所以修复方案使用了这种方式,保证\n\r 匹配上
notion image

StrictHttpFirewall

在看到这位老哥的分析文章的时候看到StrictHttpFirewall 这个名词,又学到一个新鲜玩意了
在 SpringSecurity 中提供了一个 HttpFirewall 接口,是一个请求防火墙,它可以自动处理掉一些非法请求,该接口具体实现了两个类,一个是严格模式的防火墙设置(StrictHttpFirewall),还有一个默认防火墙设置(DefaultHttpFirewall),Spring Security 中默认使用的是 StrictHttpFirewall。
notion image
这个类里面设置一堆的限制内容,具体地可以查看源码:
notion image
如果需要修改这些限制,只需要自己提供一个 StrictHttpFirewall 实例,大都是这样的格式,具体地也在那篇文章里描述了
StrictHttpFirewall firewall = new StrictHttpFirewall();
firewall.setxxxxxxxxxxx(true);
总的来说,这个东西限制住了很多东西,比如平常在Tomcat场景下的一些绕过方法比如/.././;/ 不允许出现,就算这些东西编码了,也还是会被杀掉,感觉这东西还是比较牛逼的,但是%0a,%0d 好像并没有出现在这段代码里面,可能这就是这个东西在这个CVE场景下没有其作用的原因吧

再仔细瞅瞅SpringSecurity是怎么处理路由的

调试过程关于SpringSecurity 认证处理的部分
notion image
数据流会从org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager#check 函数进入,而SpringSecurity 路径正则匹配的关键点在org.springframework.security.web.util.matcher.RegexRequestMatcher#matches 函数里面,注释也说了这个函数的作用:
Performs the match of the request URL (servletPath + pathInfo + queryString ) against the compiled pattern. If the query string is present, a question mark will be prepended.
其实本质上又是用了HttpServletRequest 那几个函数进行重新构造然后再合成字符串,然后再去正则匹配,前面的处理没问题,这个CVE最后问题是出现正则匹配上
notion image
 

总结

  1. %0a,%0d的Bypass方式,前提是正则匹配规则是类似这样的形式RegexRequestMatcher("/aaa/.*", null)
  1. SpringSecurity自身的一些特性,比如Firewall

参考


© 4me 2021 - 2024