
Step-by-step demonstration of CVE-2022-22978 authorization bypass in Spring Security's RegexRequestMatcher, with vulnerable app setup, payload execution, and fix verification.
According to the information I have gathered, this vulnerability relates to the RegexRequestMatcher class in the Spring Security framework. Specifically, applications using RegexRequestMatcher where the regular expression contains a dot (.) can be bypassed using the characters \r(%0a) and \n(%0d); thus attackers can access disallowed 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 perform a static analysis of this vulnerability. Specifically, I used the commit comparison feature between versions 5.6.3 (vulnerable version) and 5.6.4 (fixed version) on Github. See the following link: Comparing 5.6.3...5.6.4 · spring-projects/spring-security (github.com)

I checked 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 three classes in the java.util.regex package, used for processing regular expressions.Pattern.DOTALL: When using this flag, “.” in the regular expression will match all characters, including line terminators such as \n , \r.Pattern.CASE_INSENSITIVE: ignores uppercase/lowercase characters.
By default, the . in a regular expression matches all characters except line terminators like \n, \r. Therefore, if there is a regex function validating a pattern of some string, that regex 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 above regex still cannot match. Therefore, in version 5.6.4, an additional check for this case was added in RegexRequestMatcherTests.java. Specifically, it converts %0d and %0a to \n and \r respectively before checking with the 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 the text This is a CVE-2022-22978 demo when a request is made to the path /admin/*

Step 3: Set up an authentication mechanism for every time a user accesses the path /admin/<any> by 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 using Apache Tomcat listening on port 8080. Access the path /admin/xyz (any path starting with /admin/).

The result returns a 403 Forbidden code, meaning access is denied due to lack of authentication.
Now, exploit the vulnerability of the regexMatchers function in Spring Security (version 5.6.3) which does not match line terminator characters like \r(%0d) and \n(%0a) → we can access the above path without authentication using the payload /admin/%0dxyz.

Similarly with the payload /admin/%0axyz

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

At this point, the app no longer returns the response 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