根据我研究的信息,这是与Spring Security框架中的RegexRequestMatcher类相关的一个漏洞。具体来说,使用RegexRequestMatcher且正则表达式中包含点号(.)的应用程序,可以通过字符**\r(%0a)、\n(%0d)**绕过;从而使攻击者无需认证即可访问不允许的路径。
受影响的Spring Security框架版本:
5.5.x 低于 5.5.75.6.x 低于 5.6.4我们需要访问Spring Security的源代码来静态分析此漏洞。具体来说,我使用Github的版本对比功能,比较了5.6.3(受影响版本)和5.6.4(已修复版本)之间的提交。参见以下链接:Comparing 5.6.3...5.6.4 · spring-projects/spring-security (github.com)

我检查了RegexRequestMatcher类中的更改。可以看出,在版本5.6.4中,该类使用了Pattern.DOTALL,而不是版本5.6.3中默认的点号(.)。
其中:
Pattern:是java.util.regex包中的三个类之一,用于处理正则表达式。Pattern.DOTALL:使用此标志时,正则表达式中的“.”会匹配所有字符,包括换行符如\n , \r。Pattern.CASE_INSENSITIVE:不区分大小写。
默认情况下,正则表达式中的点号(.)会匹配所有字符,除了换行符(如\n, \r)。因此,如果某个函数使用正则表达式验证字符串的模式,当字符串中包含换行符时,该正则表达式将无法匹配。为了避免这种情况,可以使用Pattern.DOTALL标志。
然而,如果有人故意使用%0d代替\n或%0a代替\r,上述正则表达式仍然无法匹配。因此,在版本5.6.4中,RegexRequestMatcherTests.java中添加了额外的检查。具体来说,它会将%0d和%0a分别转换为\n和\r,然后再用正则表达式检查。

步骤1: 使用Spring Initializr创建一个Spring Boot Web应用程序,附带的依赖项包括Spring Security和Spring Web。

步骤2: 创建一个Controller,当请求到达路径/admin/*时,打印文本This is a CVE-2022-22978 demo。

步骤3: 设置每次用户访问路径/admin/<任何>时都需要认证,使用regexMatchers("/admin/.*").authenticated()。这正是攻击者利用的漏洞,无需认证即可查看/admin/<任何>页面的内容。

步骤4: 在配置文件中,声明包含漏洞的Spring Security版本。这里我选择版本5.6.3。

步骤5: 使用命令gradlew bootRun运行应用程序,程序默认使用Apache Tomcat监听8080端口。我们访问路径/admin/xyz(只要以/admin/开头的路径即可)。

结果返回403 Forbidden,表示由于未认证无法访问。
此时,利用Sping Security(版本5.6.3)中regexMatchers函数的漏洞,它不匹配换行符(如\r(%0d)和\n(%0a))→ 我们可以通过payload /admin/%0dxyz无需认证即可访问上述路径。

同样,使用payload /admin/%0axyz。

至此,我们仅用非常简单的payload就成功利用了CVE-2022-22978漏洞。
5.7.1。
使用类似的payload尝试攻击Web:/admin/%0dxyz

此时,应用程序不再返回攻击者期望的响应。
git clone https://github.com/ducluongtran9121/CVE-2022-22978-PoC.git
cd CVE-2022-22978-PoC
gradlew bootRun
Java 18
Gradle 7.4.1