
# Laboratoire pratique : Injection OGNL Apache Struts2 (CVE-2017-5638) Laboratoire pratique démontrant l'injection OGNL Apache Struts2 (CVE-2017-5638) avec analyse système pas à pas, exploitation, contournement de sandbox et techniques de post-exploitation pour l'enseignement des tests d'intrusion.

Après le démarrage du conteneur, les journaux Struts2 montrent que l'application charge des fichiers de configuration familiers tels que struts-default.xml, struts-plugin.xml et struts.xml. Cela confirme que le framework utilisé est Apache Struts2.

Un point notable se trouve dans la ligne :
Choosing bean (jakarta) for (org.apache.struts2.dispatcher.multipart.MultiPartRequest)
Cette ligne indique que Struts2 choisit le parseur multipart Jakarta (analyseur de données d'upload multipart) pour traiter les requêtes de type multipart/form-data, que l'on rencontre couramment dans les fonctionnalités d'upload de fichiers.
C'est un signal crucial lors de l'analyse de S2-045 / CVE-2017-5638, car cette vulnérabilité est liée au processus par lequel Struts2 gère les erreurs lors de l'analyse des requêtes multipart, en particulier avec un en-tête Content-Type invalide.
Cependant, ce journal prouve seulement que l'application utilise Struts2 et un gestionnaire multipart de type Jakarta. Cela ne suffit pas encore à conclure que l'application est définitivement vulnérable. Pour confirmer, il faut déterminer la version de struts2-core et la comparer à la plage de versions affectées.



En accédant au service web avec curl, les en-têtes de réponse montrent que l'application s'exécute sur Jetty 9.2.11.v20150529. Cette information permet d'identifier l'environnement qui exécute l'application (conteneur de servlets), mais ne révèle pas directement la version de Struts2.
L'interface web renvoie la page Struts2 Showcase - Fileupload sample, avec un formulaire d'upload utilisant :
method="POST" enctype="multipart/form-data" action="/upload.action"
Cela correspond au journal précédent où Struts2 choisissait jakarta pour MultiPartRequest : l'application dispose bien d'un flux de traitement d'upload de fichiers via multipart/form-data.
⇒ Réflexion : Le point de terminaison /upload.action utilise multipart/form-data, ce qui correspond au mécanisme que Struts2 traite via Jakarta MultiPartRequest. C'est un signe qui renforce la suspicion de S2-045/CVE-2017-5638, mais il faut déterminer la version de Struts2 avant de conclure que l'application est vulnérable. Ensuite, une vérification plus approfondie est encore nécessaire concernant la version de struts2-core et la façon dont l'application gère les erreurs lorsqu'elle reçoit un Content-Type invalide.
Après avoir identifié que l'application dispose d'un point de terminaison d'upload utilisant multipart/form-data, l'étape suivante de l'analyse consiste à trouver la version réelle de Struts2. C'est crucial car les signes précédents montraient seulement que l'application dispose d'un mécanisme lié à l'upload multipart, ce qui ne suffit pas encore à conclure qu'elle est vulnérable.

Après avoir identifié le bon conteneur desservant le point de terminaison 8001, la vérification des bibliothèques est effectuée directement à l'intérieur du conteneur project1-lab01-1.
Le résultat a trouvé le fichier struts2-core :
/root/.m2/repository/org/apache/struts/struts2-core/2.3.30/struts2-core-2.3.30.jar
À partir de ce chemin, on peut déterminer que l'application utilise Apache Struts2 2.3.30.

En comparant cela avec la vulnérabilité publiée CVE-2017-5638 / S2-045, celle-ci affecte de nombreuses versions plus anciennes de Struts2, y compris la branche 2.3.x antérieure au correctif. Lorsqu'on combine cela avec :
Framework: Apache Struts2 Version: 2.3.30 Parseur multipart: Jakarta Point de terminaison: /upload.action Content-Type: multipart/form-data
La chaîne de conditions de l'analyse devient plus claire :
`Version Struts2 2.3.30 < Version 2.3.32
Cependant, d'un point de vue analytique, une version vulnérable n'est qu'une preuve du potentiel d'être affecté. Pour confirmer au niveau comportemental, il faut envoyer une requête multipart anormale et observer la réponse/les journaux pour voir si elle entre dans la branche de gestion des erreurs du parseur multipart de Struts2.
⇒ Réflexion : À ce stade, il ne s'agit plus seulement d'identifier le framework ; la version 2.3.30 confirme que l'application se situe dans la plage de versions affectées de S2-045/CVE-2017-5638. L'étape restante consiste à vérifier le comportement de gestion des erreurs multipart pour compléter la chaîne de preuves.

Nous devons vérifier si les requêtes envoyées à /upload.action passent réellement par le mécanisme de traitement multipart de Struts2. Ici, j'utilise la commande curl avec l'option -F pour tester le mécanisme de traitement. Et le résultat renvoyé se décompose en parties :
`
⇒ Une requête valide prouve que /upload.action passe bien par le mécanisme d'upload multipart car curl -F génère du multipart/form-data et le serveur peut analyser chaque partie de la requête.


Après avoir envoyé une requête déclarant Content-Type comme multipart/form-data mais avec un corps qui n'est pas conforme à la structure multipart, le serveur renvoie toujours HTTP 200 OK. Cependant, les champs ContentType, FileName, File et Caption sont tous vides. En vérifiant les journaux Docker, on constate qu'il n'y a pas de boundary (chaîne de séparation entre les parties du multipart), et le client reçoit toujours HTTP 200 OK. Cependant, Struts2 a en réalité rencontré une erreur lors du traitement de la requête.
Cela prouve la chaîne de preuves :
Requête multipart erronée → Struts2 enveloppe la requête → MultiPartRequestWrapper est appelé → JakartaMultiPartRequest analyse la requête → FileUploadException due à l'absence de boundary