RCE in log4j, Log4Shell, or how things can get bad quickly
Last Updated: 2021-12-10 17:08:13 UTC
by Bojan Zdrnja (Version: 1)
If you have been following developments on Twitter and various other security sources, by now you have undoubtedly heard about the latest vulnerability in the very popular Apache log4j library.
log4j is a very popular logging package for Java. It is very powerful and flexible and, even from my own experience, is used in almost every Java application that I have ever encountered. No wonder, it allows you to just create an instance of the log4j class and then easily use it for logging, based on provided configuration parameters (typically set in the log4j.properties file).
Yesterday a PoC for a Remote Code Execution vulnerability in log4j was published. The exploit is actually unbelievably simple – which makes it very, very scary at the same time.
The vulnerability is in the JNDI lookup feature of the log4j library. While the background around this is very complex, exploitation actually is not (as you will see below in couple redacted screenshots).
The JNDI lookup feature of log4j allows variables to be retrieved via JNDI - Java Naming and Directory Interface. This is an API that that provides naming and directory functionality to Java applications. While there are many possibilities, the log4j one supports (AFAIK) LDAP and RMI (Remote Method Invocation).
In other words, when a new log entry is being created, and log4j encounters a JNDI reference, it will actually literally go to the supplied resource and fetch whatever it needs to fetch in order to resolve the required variable. And in this process, it might even download remote classes and execute them!
Below is a simple initial PoC that demonstrates how the vulnerability can be exploited:
As you can see above, in order to initially exploit the vulnerability, an attacker just needs to literally supply the JNDI reference (the text you can see in the source code). When that input gets logged by log4j, it will parse the text, see the reference and try to resolve it. And this is where the problem really is.
Depending on the JNDI reference, the log4j library will now either perform an LDAP query or an RMI query to the target URL. This is where an attacker can use the marshalsec package by Moritz Bechler, available at https://github.com/mbechler/marshalsec
This package supports, among other things JNDI reference indirection – it allows an attacker to setup a server that will accept the incoming JNDI lookup (either LDAP or RMI) and then automatically create a redirection that will point the client (in our case the log4j library) to the target codebase. The library will then follow the redirection and visit the codebase server (which is accessed over the HTTP protocol), fetch a class that is served there and execute it! Scary.
The figure below shows the marshalsec package created a JNDI reference indirection server using the RMI protocol (to use a different one than the PoC). You can see that a client accessed the server and was redirected to a remote classloading stub where the final class is waiting to be executed.
This final class is just a simple Java class that can execute anything that an attacker wishes to execute – here’s an example for the LDAP reference that will execute netcat to send a shell back to the attacker:
And really it is that simple (provided you can juggle your way around Java).
Now, you might wonder what is the impact of this? The one important thing to be aware of here is that *any application* that uses a vulnerable log4j version is affected. It does not matter if this is a server side application, or a client side application (!!!) – as long as it reads some input from an attacker, and passes that to the log4 library, there is an exploitation path, which means that even client side applications are potentially affected (and fixing might take months :/).
Since the cat is out of the bag, and due to exploitation being relatively simple, we would suggest that you try to apply one of the workarounds as soon as possible:
- A new log4j library has been released, version 2.15.0 that fixes the vulnerability. This is, of course, the best fix, but it might require recompilation and redistribution of packages
- If you are using version 2.10.0 you can set a property called formatMsgNoLookups to true to prevent lookups. This can be passed as a parameter too.
- For older versions you will need to modify logging patterns as specified here: https://issues.apache.org/jira/browse/LOG4J2-2109
Since the exploit requires the affected server/client to reach out to another server (that will supply the JNDI reference) on the Internet, the following actions can be performed:
- As always, block any outgoing traffic that is not required. If you have a server running a Java application that only needs to accept incoming traffic, prevent everything outgoing.
- If you do any traffic inspection, check for LDAP and RMI protocols.
Finally, as my fellow handler @xme noticed – this is already being exploited as part of a User Agent header:
I presume that these (simple) attackers are observing posted PoC exploits where one demo used the User Agent field, but we should stress out that *absolutely any input field* that is controlled by an attacker, and passed to the log4j library can lead to remote code execution.
Based on the activity already captured by our honeypots and the amount of information about the vulnerability, we discussed and reviewed the InfoCon rubrik. We decided to switch to the "Yellow" level until the situation will be clearer. Many vendors still have to investigate and fix the problem in their applications/systems.
There's also a TON of other big-name projects that use log4j2 tho. This was just the first one I looked into while figuring out what else in the infrastructure at $DAY_JOB uses log4j2...
Dec 10th 2021
1 year ago
They are other prefixes available:
And they can be combined:
Dec 11th 2021
1 year ago
Dec 13th 2021
1 year ago
Dec 18th 2021
1 year ago