Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2022-22965 — Análisis técnico en profundidad de CVE-2022-22965 (Spring4Shell) con configuración del entorno, recorrido de depuración y desglose de la cadena de explotación para la práctica de laboratorio educativo. | Kitploit
Herramientas/GitHubGitHub/khidottrivi/cve-2022-22965
Análisis de VulnerabilidadesAnálisis de CódigoExplotaciónExplotación de Aplicaciones WebAprendizaje y EducaciónLabs y Práctica
GitHubkhidottrivi/cve-2022-22965

CVE-2022-22965

Análisis técnico en profundidad de CVE-2022-22965 (Spring4Shell) con configuración del entorno, recorrido de depuración y desglose de la cadena de explotación para la práctica de laboratorio educativo.

Ver Repositorio
4hace 4 añosAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

Análisis de CVE-2022-22965 (Spring4Shell)

Descripción de la vulnerabilidad

Spring4Shell es el nombre de un CVE que existe en Spring Core del Spring Framework.

Con una puntuación CVSS 3.x de 9.8, la vulnerabilidad está clasificada en el nivel de riesgo más alto (crítico). Esta vulnerabilidad permite a un atacante ejecutar código de explotación de forma remota y controlar el servidor que contiene la vulnerabilidad.

Junto con la popularidad de Spring Core en Internet y la gravedad del impacto de Spring4Shell, los expertos consideran que esta vulnerabilidad tiene un impacto no menor al de Log4shell.

Alcance de la afectación

Spring4Shell no afecta a todas las aplicaciones web que utilizan Spring Framework en Internet, sino que requiere que la aplicación web cumpla con los siguientes factores:

  • La aplicación utiliza Spring Framework versión < 5.2, 5.2.0 – 5.2.19 o 5.3.0 - 5.3.17
  • La aplicación utiliza una de las dos dependencias Spring-webmvc o Spring-webflux
  • La aplicación utiliza Java con versión de JDK >= 9
  • La aplicación está empaquetada como un archivo web Java tradicional (archivo .war) y se despliega en Tomcat (no se ha detectado la vulnerabilidad en aplicaciones que se ejecutan con Springboot)

Configuración del entorno

El entorno que configuro tendrá los siguientes parámetros:

  • Spring Framework 5.1.0
  • Dependencia Spring-webmvc 5.1.0
  • JDK 11.0.13 (uso Kali 2021.4a en una máquina virtual y esta versión de Java es la que viene preinstalada)
  • Apache Tomcat 9.0.45

Creación del entorno, proyecto con la vulnerabilidad y configuración de depuración con Intellij

  1. Instalación de Apache Tomcat

    Como se mencionó anteriormente, uso Kali 2021.4a y Apache Tomcat 9.0.45. Si no sabes cómo instalar Apache Tomcat y deseas hacerlo en Kali Linux, puedes consultar este enlace.

    Nota: Reemplaza el enlace https://mirror.kiu.ac.ug/apache/tomcat/tomcat-9/v9.0.45/bin/apache-tomcat-9.0.45.tar.gz por https://archive.apache.org/dist/tomcat/tomcat-9/v9.0.45/bin/apache-tomcat-9.0.45.tar.gz

  2. Elección del IDE

    Necesitamos un IDE para codificar el proyecto, empaquetarlo como archivo .war y, algo muy importante, depurar. Yo uso Intellij, pero puedes usar Eclipse, Netbeans, etc., siempre que el IDE soporte Java.

  3. Creación de un proyecto simple que contenga la vulnerabilidad

    Mi proyecto es muy simple y consta de:

    • un modelo HelloWorld.java

      Untitled

    • un controlador HelloWorldController.java

      Untitled

    • una vista hello.jsp

      Untitled

  4. Construcción del archivo .war

    Para empaquetar el proyecto, haz lo siguiente: Build -> Build Artifacts -> helloworld:war -> Build.

    Espera a que el proceso de Build se complete con éxito; en ese momento, el proyecto tendrá una carpeta adicional llamada out. Ve a ./out/artifacts/your_war_name/ y verás un archivo your_war_name.war; este archivo .war es el proyecto web compilado y empaquetado, y se puede usar para desplegarlo en servlets Java como Apache Tomcat.

    Si Build Artifacts aparece atenuado (no se puede construir), significa que aún no se ha configurado Build Artifacts para este proyecto. Ve a: File -> Project Structure -> Artifacts -> Elimina todos los artifacts existentes -> Add (signo +) -> Web Application: Exploded -> From Modules... -> OK (finaliza la creación de Exploded) > Add (signo +) -> Web Application: Archive -> For 'helloworld:war exploded' -> OK. Luego repite el proceso de Build Artifacts.

Análisis detallado

Primero, analizaré el proyecto que estoy usando para depurar. Como mencioné anteriormente, este proyecto es muy simple y consta de:

  • Un modelo HelloWorld.java, donde el objeto HelloWorld tiene dos atributos: message (string) y person (string), junto con sus respectivos setters y getters (debido a esta estructura simple, este objeto se llama Plain Old Java Object - POJO). En el proyecto debe existir una clase POJO: esta es una condición necesaria para poder explotar la vulnerabilidad Spring4Shell.
  • Un controlador HelloWorldController.java. En esta clase hay un método helloPost que recibe como parámetros de entrada un objeto helloWorld (HelloWorld) y un modelo (Model). Dentro del método helloPost se agregan atributos al modelo a partir de los valores de las propiedades de helloWorld (person y message). Esta es la segunda condición para explotar Spring4Shell: debe haber un controlador que reciba como entrada un objeto POJO.
  • Una vista hello.jsp. En este archivo hello.jsp se invocan los atributos del modelo (enviados desde el controlador HelloWorldController.java) y se muestran al usuario.

Tengo un ejemplo como el siguiente:

Untitled

La aplicación toma la información de los parámetros de la solicitud POST y crea un objeto helloWorld{"person":"Leo", "message":"Hi there"}; este objeto helloWorld es la entrada para el método helloPost. La aplicación realiza las tareas que mencioné anteriormente para devolver al usuario esa respuesta.

El proceso de convertir los parámetros del cuerpo de la solicitud POST en el objeto helloWorld lo realiza Spring de forma automática. Entonces, ¿cómo lo hace y verifica los parámetros de entrada?

Clase fuente (Source): CachedIntrospectionResults

Esta imagen se capturó durante el proceso de depuración; el ejemplo se realizó con una solicitud cuyo cuerpo es "class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT" (llamo a la izquierda (traza de pila) como (1) y a la derecha como (2)):

Untitled

En (1) he resaltado los puntos importantes (mirando de abajo hacia arriba). Spring aplicará applyPropertyValue al objeto helloWorld a partir de los parámetros de la solicitud POST. Y si los parámetros son simplemente person=Leo&message=Hi%20there, Spring podrá encontrar que la clave 'person' corresponde a helloWorld.person, y 'message' a helloWorld.message.

Pero Spring también permite enviar objetos a través de una solicitud HTTP (decir que se envían objetos a través de HTTP es un poco exagerado, pero se entiende de forma simple). Supongamos que el atributo person ya no es un string, sino un objeto Person, y dentro de Person hay dos atributos secundarios: name (string) y age (int). Para enviar la información de este objeto Person al servidor, sería así: "person.name=Leo&person.age=23".

Entonces, el formato de los parámetros pasa a ser A.B.C.D… = X en lugar de A = X. Para procesar el formato A.B.C.D… = X, supongamos un parámetro como A.B.C = X; de forma simplificada, Spring haría lo siguiente: convertir la cadena en getA.getB.setC(X).

No explicaré qué es getA, sino que daré un ejemplo con el cuerpo de la solicitud "person.name=Leo&person.age=23". Spring buscará en el objeto helloWorld si existe el atributo person y el método getPerson; si existe, Spring llamará a helloWorld.getPerson(). En ese momento, Spring obtendrá un objeto de tipo Person, que llamaremos temporalmente person1. Luego, Spring buscará en person1 si existe un atributo 'name' y el método setName (porque después de 'name' viene '='). Si existe, Spring llamará a setName(Leo) para person1.

Con person.age, Spring no volverá a empezar desde el principio para encontrar person y luego age, sino que reutilizará los objetos anteriores, en este caso helloWorld y person1.

Después de estos pasos, en el servidor tendremos un objeto helloWorld{person:{name:"Leo", age:23}} (ignoramos temporalmente el atributo message).

Entonces, ¿cómo logra Spring encontrar los atributos de cada objeto, por ejemplo, el atributo 'person' del objeto helloWorld?

Observa la parte superior de (1), la función CachedIntrospectionResults(beanClass). Esta función enumera los atributos de beanClass. Fíjate en (2): cuando beanClass es model.HelloWorld, hay 3 atributos. Sin embargo, el modelo HelloWorld que creé solo tiene dos atributos: 'person' y 'message'. Por lo tanto, la función ha devuelto un atributo adicional 'class'. Si expandes la fila 'class', verás que el tipo de propiedad es 'java.lang.class'

Por lo tanto, podemos afectar un objeto class de tipo java.lang.class -> ¡Esta es la fuente (source) de Spring4shell!

CVE-2010-1622

Relacionado con la fuente anterior, existe un CVE-2010-1622 que explota esta fuente. El autor de CVE-2010-1622 explotó esta fuente con el payload class.classLoader.URLs[0] = X.

Esto se debe a que la clase java.lang.class contiene el método getClassLoader() que devuelve un objeto ClassLoader, y este ClassLoader puede afectar el array URLs de Tomcat (utilizado para cargar recursos). Al poder afectar URLs, un atacante puede cambiar el valor de URLs[0] a una dirección URL para conectarse de forma remota a un archivo Jar malicioso (controlado por el atacante).

Para corregir este error, Spring implementó un filtro (lista negra) en la función CachedIntrospectionResults(beanClass):

Untitled

Si 'beanClass' == Class.class (java.lang.class), entonces pd debe ser diferente de 'classLoader' y 'protectionDomain'. La prueba es que después de que CachedIntrospectionResults carga todos los atributos de java.lang.class, no aparecen los dos atributos 'classLoader' y 'protectionDomain':

Untitled

Pero, a partir de JDK 9, Class.class tiene un atributo adicional llamado 'module', y dentro de Class.module hay un atributo classLoader:

Untitled

→ Por lo tanto, al usar JDK 9 o superior, ¡se puede eludir la lista negra de Spring!

Clase destino (Sink): AccessLogValue

Basándonos en el PoC público de la vulnerabilidad Spring4Shell, podemos ver que el payload que usan tiene la forma:

class.module.classloader.resources.context.parent.pipeline.first ⇔ Class.getModule().getClassLoader().getResources().getContext().getParent().getPipeline().getFirst()

Mediante la depuración, podemos ver la siguiente cadena de gadgets:

java.lang.class.getModule() -> java.lang.module.getClassLoader() -> org.apache.catalia.loader.ParallelWebappClassLoader.getResources() -> org.apache.catalia.webresources.StandardRoot.getContext() -> org.apache.catalia.core.StandardContext.getParent() -> org.apache.catalia.core.StandardHost.getPipeline() -> org.apache.catalia.core.StandardPipeline.getFirst() -> org.apache.catalia.valves.AccessLogValue.

Y la clase AccessLogValue tiene los siguientes atributos:

Untitled

Podemos obtener un objeto AccessLogValue, y este AccessLogValue afecta la escritura de registros (logs) de Tomcat.

→ Podemos crear un archivo en el servidor estableciendo los atributos del objeto AccessLogValue en el servidor Tomcat. Para ello, en el PoC establecen los atributos Prefix, Suffix, Pattern, Directory y fileDateFormat. La solicitud payload será la siguiente:

"class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bprefix%7Di%20java.io.InputStream%20in%20%3D%20%25%7Bc%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=shell&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="

  • Lista de puntos de interrupción (Breakpoints)

    Para facilitar el proceso de depuración, puedes colocar breakpoints en los siguientes puntos:

    Untitled

Conclusión

Este análisis no debería tener una conclusión; esta sección se añade solo para que quede completa.

Si estás buscando cómo solucionarlo, está aquí.

Descargar herramienta
  • Despliegue y configuración de depuración

    • Despliegue

      Para desplegar un archivo .war en Apache Tomcat, simplemente copia el archivo .war en la carpeta /webapps dentro del directorio de Apache Tomcat (por ejemplo, en mi caso, copio el archivo helloworld.war (lo renombré para mayor comodidad) en /opt/tomcat/apache-tomcat-9.0.45/webapps/). Luego, inicia el servidor Tomcat de dos maneras (en Linux):

      • /opt/tomcat/apache-tomcat-9.0.45/bin/catalina.sh start (la aplicación se ejecutará con los permisos del usuario que ejecuta el comando, en mi caso root)
      • sudo service tomcat start (la aplicación normalmente se ejecutará con permisos de tomcat, dependiendo de cómo configures el servicio al instalar Apache Tomcat)

      Una vez desplegado, accede a http://localhost:8080/helloworld

    • Configuración de depuración

      Para configurar la depuración remota de Tomcat, haz lo siguiente:

      1. En el servidor:

        • Abre el archivo catalina.sh y cambia el valor de localhost por la IP de la máquina virtual en el parámetro JPDA_ADDRESS

          Untitled

        • Reinicia el servidor Tomcat con: /opt/tomcat/apache-tomcat-9.0.45/bin/catalina.sh jpda start. En este momento, además de abrir el puerto 8080 para el servidor HTTP, Tomcat abrirá el puerto 8000 para que podamos conectarnos y depurar.

        Nota: En esta parte de la depuración, yo ejecuto Intellij en Windows 10 y Tomcat en una máquina virtual Kali, por lo que necesito cambiar JPDA_ADDRESS. Si configuras tanto Intellij como Tomcat en la misma máquina, no es necesario cambiarlo.

      2. En Intellij:

        • Ve a Run -> Edit Configurations... -> Add (signo +) -> Remote JVM Debug

        • Pon un nombre -> modifica Host y Port para que coincidan con la IP y el puerto que configuraste en catalina.sh -> OK -> Shift + F9 (inicia la depuración)

          Untitled