
PoC della vulnerabilità CVE-2022-22978 nel framework Spring Security
Secondo le informazioni che ho trovato, questa è una vulnerabilità relativa alla classe RegexRequestMatcher nel framework Spring Security. In particolare, le applicazioni che usano RegexRequestMatcher con un'espressione regolare contenente un punto (.) possono essere aggirate con i caratteri \r(%0a), \n(%0d); di conseguenza gli attaccanti possono accedere a percorsi non consentiti senza autenticazione.
Le versioni del framework Spring Security affette dalla vulnerabilità:
5.5.x precedenti alla 5.5.75.6.x precedenti alla 5.6.4Dobbiamo accedere al codice sorgente di Spring Security per analizzare staticamente questa vulnerabilità. Nello specifico, ho usato la funzione di confronto dei commit tra le versioni 5.6.3 (versione vulnerabile) e 5.6.4 (versione corretta) di Github. Vedi il link seguente: Confronto 5.6.3...5.6.4 · spring-projects/spring-security (github.com)

Ho verificato le modifiche nella classe RegexRequestMatcher. Si può notare che nella versione 5.6.4 questa classe usa Pattern.DOTALL invece del . predefinito della versione 5.6.3.
In particolare:
Pattern: è una delle tre classi del pacchetto java.util.regex, usata per elaborare le espressioni regolari.Pattern.DOTALL: usando questo flag, il . nelle espressioni regolari corrisponde a tutti i caratteri, inclusi i caratteri di nuova riga come \n , \r.Pattern.CASE_INSENSITIVE: non distingue tra maiuscole e minuscole.
Per impostazione predefinita, il . nelle espressioni regolari corrisponde a tutti i caratteri tranne i caratteri di nuova riga come \n, \r. In questo caso, se una funzione regex valida il pattern di una stringa, non troverà corrispondenza se la stringa contiene caratteri di nuova riga. 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 può comunque trovare corrispondenza. Per questo, nella versione 5.6.4, è stato aggiunto un controllo per questo caso 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 con Spring Initializr con 2 dipendenze: Spring Security e Spring Web.

Passo 2: Creare un Controller che stampi il testo This is a CVE-2022-22978 demo quando viene ricevuta una richiesta sul percorso /admin/*.

Passo 3: Impostare un meccanismo di autenticazione ogni volta che l'utente accede al percorso /admin/<bất kì> usando regexMatchers("/admin/.*").authenticated(). Questa è la vulnerabilità che gli attaccanti sfruttano per vedere il contenuto delle pagine /admin/<bất kì> 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 usa di default Apache Tomcat in ascolto sulla porta 8080. Accediamo al percorso /admin/xyz (qualunque percorso va bene purché inizi con /admin/).

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

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

Così siamo riusciti a sfruttare con successo la vulnerabilità CVE-2022-22978 con un payload estremamente semplice.
5.7.1.
Proviamo ad attaccare l'applicazione web con lo stesso payload: /admin/%0dxyz.

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