
Laboratorio práctico que demuestra la inyección OGNL de Apache Struts2 (CVE-2017-5638) con análisis de sistema paso a paso, explotación, bypass de sandbox y técnicas de post-explotación para la educación en pruebas de penetración.

Después de iniciar el contenedor, los registros de Struts2 muestran que la aplicación carga archivos de configuración conocidos como struts-default.xml, struts-plugin.xml y struts.xml. Esto confirma que el framework en uso es Apache Struts2.

Un punto notable se encuentra en la línea:
Choosing bean (jakarta) for (org.apache.struts2.dispatcher.multipart.MultiPartRequest)
Esta línea indica que Struts2 está eligiendo el parser multipart de Jakarta (analizador de datos de subida multipart) para manejar solicitudes de tipo multipart/form-data, que se encuentran comúnmente en la funcionalidad de subida de archivos.
Esta es una señal crucial al analizar S2-045 / CVE-2017-5638, ya que esta vulnerabilidad está relacionada con el proceso en el que Struts2 maneja errores al analizar solicitudes multipart, especialmente con una cabecera Content-Type no válida.
Sin embargo, este registro solo demuestra que la aplicación usa Struts2 y un manejador multipart de estilo Jakarta. Aún no es suficiente para concluir que la aplicación es definitivamente vulnerable. Para confirmarlo, necesitamos determinar la versión de struts2-core y compararla con el rango de versiones afectadas.



Al acceder al servicio web con curl, las cabeceras de respuesta muestran que la aplicación se ejecuta en Jetty 9.2.11.v20150529. Esta información ayuda a identificar el entorno que ejecuta la aplicación (contenedor de servlets), pero no revela directamente la versión de Struts2.
La interfaz web devuelve la página Struts2 Showcase - Fileupload sample, con un formulario de subida que usa:
method="POST" enctype="multipart/form-data" action="/upload.action"
Esto coincide con el registro anterior donde Struts2 eligió jakarta para MultiPartRequest: la aplicación efectivamente tiene un flujo de manejo de subida de archivos mediante multipart/form-data.
⇒ Pensamiento: El endpoint /upload.action usa multipart/form-data, lo que coincide con el mecanismo que Struts2 procesa a través de Jakarta MultiPartRequest. Esto es una señal que refuerza la sospecha de S2-045/CVE-2017-5638, pero necesitamos determinar la versión de Struts2 antes de concluir que la aplicación es vulnerable. A continuación, aún se necesita una verificación más profunda sobre la versión de struts2-core y cómo maneja la aplicación los errores al recibir un Content-Type no válido.
Después de identificar que la aplicación tiene un endpoint de subida que usa multipart/form-data, el siguiente paso del análisis es encontrar la versión real de Struts2. Esto es crucial porque las señales anteriores solo mostraban que la aplicación tiene un mecanismo relacionado con la subida multipart, lo cual aún no es suficiente para concluir que es vulnerable.

Después de identificar el contenedor correcto que sirve el endpoint 8001, la comprobación de las librerías se realiza directamente dentro del contenedor project1-lab01-1.
El resultado encontró el archivo struts2-core:
/root/.m2/repository/org/apache/struts/struts2-core/2.3.30/struts2-core-2.3.30.jar
A partir de esta ruta, podemos determinar que la aplicación usa Apache Struts2 2.3.30.

Comparando esto con la vulnerabilidad publicada CVE-2017-5638 / S2-045, esta afecta a muchas versiones antiguas de Struts2, incluyendo la rama 2.3.x anterior al parche. Al combinarlo con:
Framework: Apache Struts2 Version: 2.3.30 Multipart parser: Jakarta Endpoint: /upload.action Content-Type: multipart/form-data
La cadena de condiciones del análisis se vuelve más clara:
`Struts2 Version 2.3.30 < Version 2.3.32
Sin embargo, desde una perspectiva de análisis, una versión vulnerable solo es evidencia de la posibilidad de verse afectada. Para confirmarlo a nivel de comportamiento, necesitamos enviar una solicitud multipart anómala y observar la respuesta/registros para ver si entra en la rama de manejo de errores del parser multipart de Struts2.
⇒ Pensamiento: En este punto, ya no se trata solo de identificar el framework; la versión 2.3.30 confirma que la aplicación se encuentra dentro del rango de versiones afectadas por S2-045/CVE-2017-5638. El paso restante es verificar el comportamiento del manejo de errores multipart para completar la cadena de evidencia.

Necesitamos comprobar si las solicitudes enviadas a /upload.action realmente pasan por el mecanismo de procesamiento multipart de Struts2. Aquí, uso el comando curl con la opción -F para probar el mecanismo de manejo. Y el resultado devuelto se desglosa en partes:
`
⇒ Una solicitud válida demuestra que /upload.action efectivamente pasa por el mecanismo de subida multipart porque curl -F genera multipart/form-data y el servidor puede analizar cada parte de la solicitud.


Después de enviar una solicitud declarando Content-Type como multipart/form-data pero con un cuerpo que no se ajusta a la estructura multipart, el servidor aún devuelve HTTP 200 OK. Sin embargo, los campos ContentType, FileName, File y Caption están vacíos. Al revisar los registros de Docker, notamos que no hay boundary (cadena separadora entre las partes del multipart), y el cliente aún recibe HTTP 200 OK. No obstante, Struts2 en realidad encountered an error al procesar la solicitud.
Esto demuestra la cadena de evidencia:
Faulty multipart request → Struts2 wraps request → MultiPartRequestWrapper is called → JakartaMultiPartRequest parses request → FileUploadException due to missing boundary
⇒ Coincide con los componentes relacionados con S2-045/CVE-2017-5638. Por lo tanto, la cadena de condiciones es más completa: versión vulnerable, parser Jakarta, endpoint de subida y la solicitud defectuosa entra en la rama correcta de procesamiento multipart.