据我了解,此漏洞与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:不区分大小写。
步骤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状态码,意味着由于未认证而无法访问。
此时,利用Spring 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