
PoC de la vulnerabilidad CVE-2022-22978 en el framework Spring Security
Según la información que he investigado, esta es una vulnerabilidad relacionada con la clase RegexRequestMatcher en el framework Spring Security. Específicamente, las aplicaciones que usan RegexRequestMatcher cuya expresión regular contiene un punto (.) pueden ser evadidas mediante los caracteres \r(%0a) y \n(%0d); de este modo, los atacantes pueden acceder a rutas no permitidas sin autenticación.
Las versiones vulnerables del framework Spring Security son:
5.5.x anteriores a 5.5.75.6.x anteriores a 5.6.4Necesitamos acceder al código fuente de Spring Security para analizar estáticamente esta vulnerabilidad. En concreto, he usado la función de comparación de commits entre las versiones 5.6.3 (versión vulnerable) y 5.6.4 (versión corregida) de Github. Ver el siguiente enlace: Comparando 5.6.3...5.6.4 · spring-projects/spring-security (github.com)

He revisado los cambios en la clase RegexRequestMatcher. Se puede ver que, en la versión 5.6.4, esta clase usa Pattern.DOTALL en lugar del . predeterminado de la versión 5.6.3.
Donde:
Pattern : es una de las 3 clases del paquete java.util.regex, que se encarga de procesar las expresiones regulares.Pattern.DOTALL : al usar esta flag, el “.” de la expresión regular coincide con todos los caracteres, incluidos los saltos de línea como \n , \r.Pattern.CASE_INSENSITIVE: no distingue entre mayúsculas y minúsculas.
Por defecto, el . en una expresión regular coincide con todos los caracteres excepto los saltos de línea como \n, \r. Por lo tanto, si existe una función regex que valida el patrón de alguna cadena, esa función regex no coincidirá si la cadena contiene saltos de línea. Para evitar esto, se puede usar la flag Pattern.DOTALL.
Sin embargo, si alguien usa deliberadamente %0d en lugar de \n o %0a en lugar de \r, la regex anterior todavía no podrá coincidir. Por eso, en la versión 5.6.4, se añadió una comprobación adicional para este caso en RegexRequestMatcherTests.java. En concreto, convierte %0d y %0a en \n y \r respectivamente y luego hace la comprobación con la regex.

Paso 1: Crea una aplicación web Spring Boot con Spring Initializr y las 2 dependencias Spring Security y Spring Web.

Paso 2: Crea un Controller que imprima el texto This is a CVE-2022-22978 demo cuando llegue una petición a la ruta /admin/*

Paso 3: Configura un mecanismo de autenticación para cuando el usuario acceda a la ruta /admin/<bất kì> usando regexMatchers("/admin/.*").authenticated(). Esta es exactamente la vulnerabilidad que los atacantes aprovechan para ver el contenido de las páginas /admin/<bất kì> sin autenticación.

Paso 4: En el archivo de configuración, declara la versión de Spring Security que contiene la vulnerabilidad. Aquí elijo la versión 5.6.3.

Paso 5: Ejecuta la aplicación con el comando gradlew bootRun. El programa usa Apache Tomcat por defecto y escucha en el puerto 8080. Accedemos a la ruta /admin/xyz (cualquier ruta sirve siempre que empiece por /admin/).

El resultado devuelve el código 403 Forbidden, lo que significa que no se puede acceder porque no estoy autenticado.
En este punto, aprovechando la vulnerabilidad de la función regexMatchers en Spring Security (versión 5.6.3), que no coincide con los caracteres de salto de línea como \r(%0d) y \n(%0a), se puede acceder a la ruta anterior sin autenticación mediante el payload /admin/%0dxyz

Lo mismo con el payload /admin/%0axyz

Así, hemos explotado con éxito la vulnerabilidad CVE-2022-22978 con un payload extremadamente simple.
5.7.1
Intenta atacar la web con el mismo payload de antes: /admin/%0dxyz

En este caso, la aplicación ya no devuelve la respuesta que el atacante esperaba.
git clone https://github.com/ducluongtran9121/CVE-2022-22978-PoC.git
cd CVE-2022-22978-PoC
gradlew bootRun
Java 18
Gradle 7.4.1