
Proof-of-concept demonstrating authorization bypass in Spring Security's RegexRequestMatcher (CVE-2022-22978) using CRLF injection, with analysis and mitigation steps.
According to the information I gathered, this is a vulnerability related to the RegexRequestMatcher class in the Spring Security framework. Specifically, applications using RegexRequestMatcher where the regular expression contains a dot (.) can be bypassed using \r(%0a) and \n(%0d) characters; thus attackers can access unauthorized paths without authentication.
Affected versions of the Spring Security framework:
5.5.x before 5.5.75.6.x before 5.6.4We need to access the Spring Security source code to statically analyze this vulnerability. Specifically, I used GitHub's commit comparison feature between versions 5.6.3 (vulnerable version) and 5.6.4 (fixed version). See the link: Comparing 5.6.3...5.6.4 · spring-projects/spring-security (github.com)

I examined the changes in the RegexRequestMatcher class. It can be seen that in version 5.6.4, this class uses Pattern.DOTALL instead of the default . as in version 5.6.3.
Where:
Pattern is one of the three classes in the java.util.regex package, used for handling regular expressions.Pattern.DOTALL: When using this flag, "." in a regular expression matches all characters, including line terminators like \n , \r.Pattern.CASE_INSENSITIVE: ignores case.
By default, the . in a regular expression matches all characters except line terminators like \n, \r. Therefore, if a regex function validates a pattern against a string, it will not match if the string contains line terminators. To avoid this, the Pattern.DOTALL flag can be used.
However, if someone intentionally uses %0d instead of \n or %0a instead of \r, the regex still cannot match. Therefore, in version 5.6.4, an additional check was added in RegexRequestMatcherTests.java. Specifically, it converts %0d and %0a to \n and \r respectively before checking with regex.

Step 1: Create a Spring Boot web application using Spring Initializr with two dependencies: Spring Security and Spring Web.

Step 2: Create a Controller that prints This is a CVE-2022-22978 demo when a request is made to /admin/*

Step 3: Set up authentication for any user accessing the path /admin/<any> using regexMatchers("/admin/.*").authenticated(). This is the vulnerability that attackers exploit to view the content of /admin/<any> pages without authentication.

Step 4: In the configuration file, declare the version of Spring Security that contains the vulnerability. Here I choose version 5.6.3.

Step 5: Run the application with the command gradlew bootRun. The program defaults to Apache Tomcat listening on port 8080. Access the path /admin/xyz (any path under /admin/ works).

Result: 403 Forbidden returned, meaning we cannot access due to lack of authentication.
Now, exploit the vulnerability of the regexMatchers function in Spring Security (version 5.6.3) when it does not match line terminators like \r(%0d) and \n(%0a) → we can access the above path without authentication using the payload /admin/%0dxyz

Similarly with payload /admin/%0axyz

Thus, we successfully exploited CVE-2022-22978 with a very simple payload.
5.7.1
Try attacking the web with the same payload: /admin/%0dxyz

At this point, the app does not return the response that the attacker expected.
git clone https://github.com/ducluongtran9121/CVE-2022-22978-PoC.git
cd CVE-2022-22978-PoC
gradlew bootRun
Java 18
Gradle 7.4.1