
Dimostrazione passo-passo del bypass di autorizzazione CVE-2022-22978 in RegexRequestMatcher di Spring Security, con configurazione dell'app vulnerabile, esecuzione del payload e verifica della correzione.
Secondo le informazioni che ho raccolto, questa è una vulnerabilità relativa alla classe RegexRequestMatcher nel framework Spring Security. In particolare, le applicazioni che utilizzano RegexRequestMatcher in cui l'espressione regolare contiene un punto (.) possono essere aggirate utilizzando i caratteri \r(%0a) e \n(%0d); così gli attaccanti possono accedere a percorsi non consentiti senza autenticazione.
Versioni vulnerabili del framework Spring Security:
5.5.x precedenti a 5.5.75.6.x precedenti a 5.6.4Dobbiamo accedere al codice sorgente di Spring Security per un'analisi statica di questa vulnerabilità. Nello specifico, ho utilizzato la funzione di confronto dei commit tra le versioni 5.6.3 (versione vulnerabile) e 5.6.4 (versione corretta) di Github. Vedi al seguente link: Comparing 5.6.3...5.6.4 · spring-projects/spring-security (github.com)

Ho controllato le modifiche nella classe RegexRequestMatcher. Si può notare che nella versione 5.6.4, questa classe utilizza Pattern.DOTALL invece del . predefinito come nella versione 5.6.3.
Dove:
Pattern: è una delle tre classi nel pacchetto java.util.regex, che gestisce le espressioni regolari.Pattern.DOTALL: quando si utilizza questo flag, "." nell'espressione regolare corrisponde a tutti i caratteri, compresi i caratteri di newline come \n , \r.Pattern.CASE_INSENSITIVE: non distingue tra maiuscole e minuscole.
Per impostazione predefinita, il . in un'espressione regolare corrisponde a tutti i caratteri tranne i caratteri di newline come \n, \r. Quindi, se c'è una funzione regex che convalida il pattern di una stringa, quella regex non corrisponderà se la stringa contiene caratteri di newline. Per evitare ciò, si può usare il flag Pattern.DOTALL.
Tuttavia, se qualcuno usa intenzionalmente %0d invece di \n o %0a invece di \r, la regex precedente non corrisponderà comunque. Pertanto, nella versione 5.6.4, è stato aggiunto un controllo aggiuntivo in RegexRequestMatcherTests.java. Nello specifico, converte %0d e %0a rispettivamente in \n e \r prima di verificare con la regex.

Passo 1: Creare un'applicazione web Spring Boot utilizzando Spring Initializr con le due dipendenze aggiuntive Spring Security e Spring Web.

Passo 2: Creare un Controller che stampi la stringa This is a CVE-2022-22978 demo quando viene effettuata una richiesta al percorso /admin/*

Passo 3: Impostare un meccanismo di autenticazione per ogni accesso utente al percorso /admin/<qualsiasi> utilizzando regexMatchers("/admin/.*").authenticated(). Questa è la vulnerabilità che gli attaccanti sfruttano per visualizzare il contenuto delle pagine /admin/<qualsiasi> senza autenticazione.

Passo 4: Nel file di configurazione, dichiarare la versione di Spring Security che contiene la vulnerabilità. Qui scelgo la versione 5.6.3.

Passo 5: Eseguire l'applicazione con il comando gradlew bootRun, il programma utilizza di default Apache Tomcat in ascolto sulla porta 8080. Accedere al percorso /admin/xyz (qualsiasi percorso purché inizi con /admin/).

Il risultato restituisce il codice 403 Forbidden, il che significa che non possiamo accedere perché non autenticati.
A questo punto, sfruttiamo la vulnerabilità della funzione regexMatchers in Spring Security (versione 5.6.3) quando non corrisponde ai caratteri di newline come \r(%0d) e \n(%0a) → possiamo accedere al percorso sopra senza autenticazione con il payload /admin/%0dxyz

Allo stesso modo con il payload /admin/%0axyz

Così abbiamo sfruttato con successo la vulnerabilità CVE-2022-22978 con un payload estremamente semplice.
5.7.1
Proviamo ad attaccare il web con lo stesso payload di prima: /admin/%0dxyz

A questo punto, l'app non restituisce la risposta desiderata dall'attaccante.
git clone https://github.com/ducluongtran9121/CVE-2022-22978-PoC.git
cd CVE-2022-22978-PoC
gradlew bootRun
Java 18
Gradle 7.4.1