
Schritt-für-Schritt-Demonstration der CVE-2022-22978-Autorisierungsumgehung in Spring Securitys RegexRequestMatcher, mit Einrichtung der verwundbaren App, Payload-Ausführung und Fix-Verifizierung.
Nach meinen Recherchen handelt es sich um eine Schwachstelle in der Klasse RegexRequestMatcher im Spring-Security-Framework. Konkret können Anwendungen, die RegexRequestMatcher verwenden, wenn der reguläre Ausdruck einen Punkt (.) enthält, durch die Zeichen \r(%0a) und \n(%0d) umgangen werden; dadurch können Angreifer ohne Authentifizierung auf nicht erlaubte Pfade zugreifen.
Die betroffenen Versionen des Spring-Security-Frameworks:
5.5.x vor 5.5.75.6.x vor 5.6.4Wir müssen in den Quellcode von Spring Security schauen, um diese Schwachstelle statisch zu analysieren. Konkret habe ich die Commit-Vergleichsfunktion von GitHub zwischen den Versionen 5.6.3 (verwundbare Version) und 5.6.4 (behobene Version) verwendet. Siehe folgenden Link: Comparing 5.6.3...5.6.4 · spring-projects/spring-security (github.com)

Ich habe die Änderungen in der Klasse RegexRequestMatcher untersucht. Man sieht, dass diese Klasse in Version 5.6.4 Pattern.DOTALL verwendet, anstatt den standardmäßigen . wie in Version 5.6.3.
Dabei gilt:
Pattern : eine der drei Klassen im Paket java.util.regex, die für die Verarbeitung regulärer Ausdrücke zuständig ist.Pattern.DOTALL : Mit diesem Flag matcht . in regulären Ausdrücken alle Zeichen, einschließlich Zeilenumbruchzeichen wie \n , \r.Pattern.CASE_INSENSITIVE: ignoriert Groß- und Kleinschreibung.
Standardmäßig matcht der Punkt . in regulären Ausdrücken alle Zeichen außer Zeilenumbruchzeichen wie \n, \r. Wenn also eine Regex-Funktion das Muster einer Zeichenkette validiert, matcht diese Regex nicht, wenn die Zeichenkette Zeilenumbruchzeichen enthält. Um dies zu vermeiden, kann das Flag Pattern.DOTALL verwendet werden.
Wenn jedoch jemand absichtlich %0d anstelle von \n oder %0a anstelle von \r verwendet, kann die obige Regex immer noch nicht matchen. Deshalb wurde in Version 5.6.4 in RegexRequestMatcherTests.java ein zusätzlicher Check für diesen Fall hinzugefügt. Konkret werden %0d und %0a zunächst in \n bzw. \r konvertiert und dann mit der Regex geprüft.

Schritt 1: Erstelle eine Spring-Boot-Webanwendung mit Spring Initializr und den beiden Abhängigkeiten Spring Security und Spring Web.

Schritt 2: Erstelle einen Controller, der den Text This is a CVE-2022-22978 demo ausgibt, wenn eine Anfrage an den Pfad /admin/* eingeht.

Schritt 3: Richte einen Authentifizierungsmechanismus ein, der bei jedem Zugriff auf den Pfad /admin/<bất kì> greift, indem du regexMatchers("/admin/.*").authenticated() verwendest. Genau diese Schwachstelle nutzen Angreifer aus, um ohne Authentifizierung den Inhalt der Seiten /admin/<bất kì> anzusehen.

Schritt 4: In der Konfigurationsdatei deklarierst du die verwundbare Version von Spring Security. Hier wähle ich Version 5.6.3.

Schritt 5: Starte die Anwendung mit dem Befehl gradlew bootRun. Das Programm verwendet standardmäßig Apache Tomcat und lauscht auf Port 8080. Wir greifen auf den Pfad /admin/xyz zu (jeder Pfad ist möglich, solange er mit /admin/ beginnt).

Das Ergebnis ist der Code 403 Forbidden, was bedeutet, dass ich nicht zugreifen kann, weil ich nicht authentifiziert bin.
Nun nutzen wir die Schwachstelle der Funktion regexMatchers in Spring Security (Version 5.6.3) aus, da sie keine Zeilenumbruchzeichen wie \r(%0d) und \n(%0a) matcht → ich kann ohne Authentifizierung auf den obigen Pfad zugreifen, indem ich den Payload /admin/%0dxyz verwende.

Ebenso mit dem Payload /admin/%0axyz

Damit haben wir die Schwachstelle CVE-2022-22978 mit einem äußerst einfachen Payload erfolgreich ausgenutzt.
5.7.1
Versuche, die Webanwendung mit demselben Payload wie zuvor anzugreifen: /admin/%0dxyz

In diesem Fall gibt die App nicht die vom Angreifer erwartete Antwort zurück.
git clone https://github.com/ducluongtran9121/CVE-2022-22978-PoC.git
cd CVE-2022-22978-PoC
gradlew bootRun
Java 18
Gradle 7.4.1