Understanding Log4Shell —A Log4J Zero-Day Exploit
I am sure If you’re interested enough to read this blog, you are familiar with the zero-day exploit discovered recently in the log4j library which allows remote code execution. I believe we can agree that it is the most dangerous type of vulnerability. In this post, we’ll examine which applications are vulnerable, how this exploit works (with a demo application), and what actions you can take to protect yourself.
Who is vulnerable?
- Applications using java versions older than 8u191, 7u201, 6u211, and 11.01.
- Tries to log an input field with log4j.
- trustURLCodebase is set to true for either ldap or rmi. (or have Tomcat 8+ or SpringBoot 1.2.x+ in classpath)
- Using Log4j2 versions >= 2.0-beta9 and <= 2.14.1.
How does it work?
This exploit works by taking advantage of the JNDI (Java Naming and Directory Interface). JNDI is an API that provides naming and directory functionality for Java applications. It can work with registry services like RMI or directory services like LDAP. You can learn more about JNDI from the official oracle docs.
- As the first step, the attacker has to serve or mimic an LDAP or RMI server from a location that the target application server can reach and trust.
- After running the fake LDAP server with the malicious class in it, the attacker will find an endpoint that logs the input with a vulnerable version of Log4j and send a request to that endpoint which requires access to the attacker’s fake LDAP server. (e.g. “http://attacker.com/Malicious.class)
- After retrieving the request from the victim server, the attacker’s LDAP will serve a malicious class.
- After loading the Malicious.class, the victim server will execute it and enable the attacker to run any type of command on the server. Hence the name Remote Code Execution.
As soon as this exploit went public, people started to come up with different ideas and ways to take advantage of the situation. Some people are trying to use this vulnerability to run crypto miners on servers. It is not hard to imagine that this will also allow attackers to upload and run a reverse TCP payload to your server and use it to gain higher privileges. Now let’s take look at how it works in a demo project.
Demo Project
First things first, we need a server that we can direct our target. Luckily GitHub user welk1n created a simple server project that serves both RMI and LDAP endpoints. We can download, INSPECT, compile and run the source from here. We’ll set the command that we want to run as the parameter -C in quotation marks. You can see the example below.
When you run this project, it will print out multiple endpoints for different kinds of servers.
After we set our server, I’ll go ahead and create a basic application with a simple endpoint that logs the given input with log4j.
So, the issue begins when we run this server and call some of the example endpoints. It doesn’t have to be in the body or the header both can work. It doesn’t matter how you get your string into some logging method if you can achieve that this will work.
As you can see in both examples very clearly, when a request is sent to these endpoints after accessing the LDAP or RMI server, the retrieved piece of code ran on the server. This was an innocent touch command but in the wrong hands, it can be very dangerous.
Solution
The best and safest way to protect yourself from this is to upgrade your log4j library to 2.15.0-rc1. For those who can’t do that at the moment, there are some workaround fixes.
- You can modify all logging patterns you’re using with “%m{nolookups}”.
- You can pass “‐Dlog4j2.formatMsgNoLookups=True” in the startup JVM command. This will prevent the whole project from using look-ups within Log4j.
- You can create an empty or modified implementation of “org.apache.logging.log4j.core.lookup.JndiLookup” and modify your project to use your empty implementation instead of the default one.
Conclusion
This is a nasty vulnerability we’re facing today because of the widespread use of the log4j in the industry, discovering a vulnerability that allows RCE for the latest version on a popular library is pretty scary if you ask me. Fortunately, the community that builds these libraries and solutions is also supporting and responsive during these types of crises.
I hope everyone will quickly respond to the issue and update their projects so we can exterminate this pandemic.
Sources & Projects
You can get the test project source codes from here: