
Proof-of-Concept für CVE-2022-22978, der die Umgehung der Autorisierung in Spring Securitys RegexRequestMatcher mittels CRLF-Injection demonstriert, mit einer Demo-Anwendung und Fehlerbehebungsanalyse.
Den Informationen zufolge, die ich recherchiert habe, handelt es sich um eine Sicherheitslücke in der Klasse RegexRequestMatcher des Spring Security Frameworks. Konkret können Anwendungen, die RegexRequestMatcher verwenden und deren regulärer 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.
Betroffene Versionen des Spring Security Frameworks:
5.5.x vor 5.5.75.6.x vor 5.6.4Wir müssen auf den Quellcode von Spring Security zugreifen, um diese Sicherheitslücke statisch zu analysieren. Konkret verwende ich die Commit-Vergleichsfunktion zwischen den Versionen 5.6.3 (anfällige Version) und 5.6.4 (behobene Version) auf GitHub. Siehe folgenden Link: Vergleich 5.6.3...5.6.4 · spring-projects/spring-security (github.com)

Ich überprüfe die Änderungen in der Klasse RegexRequestMatcher. Es ist ersichtlich, dass in Version 5.6.4 diese Klasse Pattern.DOTALL anstelle des standardmäßigen . wie in Version 5.6.3 verwendet.
Dabei:
Pattern: ist eine der drei Klassen im Paket java.util.regex, die für die Verarbeitung regulärer Ausdrücke zuständig ist.Pattern.DOTALL: Bei Verwendung dieses Flags matcht der Punkt (.) im regulären Ausdruck alle Zeichen, einschließlich Zeilenumbruchzeichen wie \n , \r.Pattern.CASE_INSENSITIVE: ignoriert Groß-/Kleinschreibung.
Standardmäßig matcht der Punkt (.) im regulären Ausdruck alle Zeichen außer Zeilenumbruchzeichen wie \n, \r. Wenn also eine Regex-Funktion ein Muster für eine Zeichenkette validiert, wird diese Regex nicht matchen, 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. Daher wurde in Version 5.6.4 eine zusätzliche Prüfung in RegexRequestMatcherTests.java eingefügt. Konkret konvertiert sie %0d und %0a in \n bzw. \r, bevor sie mit der Regex überprüft wird.

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

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

Schritt 3: Richten Sie einen Authentifizierungsmechanismus ein, der bei jedem Zugriff auf den Pfad /admin/<beliebig> greift, indem Sie regexMatchers("/admin/.*").authenticated() verwenden. Dies ist die Schwachstelle, die Angreifer ausnutzen, um den Inhalt von Seiten unter /admin/<beliebig> ohne Authentifizierung zu sehen.

Schritt 4: In der Konfigurationsdatei deklarieren Sie die Version von Spring Security, die die Sicherheitslücke enthält. Hier wähle ich Version 5.6.3.

Schritt 5: Starten Sie die Anwendung mit dem Befehl gradlew bootRun. Das Programm verwendet standardmäßig Apache Tomcat und lauscht auf Port 8080. Greifen Sie auf den Pfad /admin/xyz zu (beliebiger Pfad, solange er mit /admin/ beginnt).

Das Ergebnis ist der Statuscode 403 Forbidden, was bedeutet, dass wir aufgrund fehlender Authentifizierung nicht zugreifen können.
Nutzen Sie nun die Schwachstelle der regexMatchers-Funktion in Spring Security (Version 5.6.3), die Zeilenumbruchzeichen wie \r(%0d) und \n(%0a) nicht matchen kann → wir können auf den obigen Pfad ohne Authentifizierung zugreifen, indem wir den Payload /admin/%0dxyz verwenden.

Analog mit dem Payload /admin/%0axyz.

Somit haben wir die Sicherheitslücke CVE-2022-22978 erfolgreich mit einem sehr einfachen Payload ausgenutzt.
5.7.1.
Versuchen Sie, die Webanwendung mit dem gleichen Payload wie oben anzugreifen: /admin/%0dxyz.

Nun gibt die App nicht die vom Angreifer gewünschte 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