All about Log4j vulnerability

Reading Time: 4 minutes

Log4J vulnerability is critical remote code execution (RCE) vulnerability (CVE-2021-44228) in Apache’s Log4j software library, versions 2.0-beta9 to 2.14.1, known as “Log4Shell.” Log4j is very broadly used in a variety of consumer and enterprise services, websites, and applications—as well as in operational technology products—to log security and performance information. An unauthenticated remote actor could exploit this vulnerability to take control of an affected system.

  • On December 10, 2021, Apache released Log4j 2.15.0 for Java 8 users to address a remote code execution (RCE) vulnerability—CVE-2021-44228.
  • On December 13, 2021, Apache released Log4j 2.12.2 for Java 7 users and Log4j 2.16.0 for Java 8 users to address a RCE vulnerability—CVE-2021-45046.
  • On December 17, 2021, Apache released Log4j 2.17.0 for Java 8 users to address a denial-of-service (DOS) vulnerability—CVE-2021-45105.

There are lots of application which usages log4j directly or indirectly. According to Sync Security found that around 60% of java application they use log4j indirectly (depending on another library) and 39.2% application using it directly.

CVSS (Common Vulnerability Scoring System) have rated this vulnerability as 10 which highest (10 out of 10) severity vulnerability. This vulnerability enable RCE (Remote Code Execution), this allow hacker to run any code on your machine. This vulnerability also named as Log4Shell which enable anyone can open remote shell on your machine.

For understanding log4j vulnerability we will first discuss about log4j and JNDI

What is log4j

Apache Log4j is a Java-based logging utility originally written by Ceki Gülcü. Log4j is Apache Open Source Framework [ ] which is develop and maintained by group of Open Source volunteered. log4j is a tool to help the programmer output log statements to a variety of output targets. In case of problems with an application, it is helpful to enable logging so that the problem can be located. With log4j it is possible to enable logging at runtime without modifying the application binary. Software developers use the Log4j framework to record user activity and the behavior of applications for debugging or reviewing later.

JNDI (Java Naming and Directory Interface):

The Java Naming and Directory Interface (JNDI) allow you to store java object in a remote location and then serialized them to your JVM. JNDI is an application programming interface (API) that provides naming and directory functionality to applications written using the Java programming language. It is defined to be independent of any specific directory service implementation. Thus a variety of directories(new, emerging, and already deployed) can be accessed in a common way.

JNDI allows distributed applications to look up services in an abstract, resource-independent way. The most common use case is to set up a database connection pool on a Java EE application server. Any application that’s deployed on that server can gain access to the connections they need using the JNDI name java:comp/env/FooBarPool without having to know the details about the connection.

enter image description here

To use the JNDI, you must have the JNDI classes and one or more service providers. The Java 2 SDK, v1.3 includes three service providers for the following naming/directory services:

  1. Lightweight Directory Access Protocol (LDAP)
  2. Common Object Request Broker Architecture (CORBA) Common Object Services (COS) name service
  3. Java Remote Method Invocation (RMI) Registry

So basically you create objects and register them on the directory services which you can later do lookup and execute operation on.

Log4J Vulnerability:

use case might be that you have centralized logging configuration from a config server and you want to serialize that configuration using JNDI and have that affect log messages like said the logging path or prefix messages with a certain value etc.

One of the feature of JNDI is JNDI lookups in log messages.

string interpolation example:

final Logger logger = LogManager.getLogger(…);
logger.error("Error message: {}", error.getMessage());

In this example log4j running error.getMessage() and putting to string which is eventually get executed by java.

another ldap example for JNDI lookup:

final Logger logger = LogManager.getLogger(…);
logger.error("{}: Error {}", "${jndi:ldap://logconfig/prefix}", error.getMessage());

here you are getting the prefix for the logging message from JNDI by passing the JNDI url as an argument, you are not just passing a value that this things resolves but you are actually passing a string value. but this is not something that java resolves but this is something you are passing to log4j. basically the difference is log4j does lookups for certain types of string. for eg:

logger.error("Inserts String here: {}", "Hello world");

if you have any old string what it does that it insert the string into curly braces,

logger.error("Looks up value and inserts: {}", "${jndi:ldap://…}"); 

however string that you are passing have special syntax which is the dollar curly then this is a clue for log4j to actually look it up. In this particular example it say that its JNDI lookup and its going to look up the value and its going to insert that in the double curlies for the template string.

another example environment variable

logger.error(“Looks up value and inserts: {}”, “${env:ENV_VALUE}”);

here in the $ part its realize that its an environment variable lookup and in this case it is going to look up this environment variable and insert the values in the double curlies.

example of Log4J vulnerability and how hacker can access security credential is following:

log4j attack example where malicious hacker try to get AWS credential key