
Laboratorio pratico che dimostra l'iniezione OGNL di Apache Struts2 (CVE-2017-5638) con analisi passo-passo del sistema, sfruttamento, bypass della sandbox e tecniche post-sfruttamento per l'educazione al penetration testing.

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.

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.



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:
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.
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.

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.

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:
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:
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.

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:
<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.


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:
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.