Hello guys, since the last couple of days, there is a lot of chaos going
into the Java world due to the Log4j2 issue which allows Remote code
execution (RCE), the CVE-2021-44228, which is designated a zero-day vulnerability. Everyone is busy whether their Java application is impacted
and given the popularity of Log4j it's a good chance that your application
will be impacted. Even if you are not using Log4j2 directly, they
might be used by the framework or library you use like
Spring Boot, Hadoop, Elastic Serach, or
Struts. This is kind of a serious issue becuase RCE Vulnarabilyt means it allows
hackers to execute code in your servers, and this has been used in past on
many breaches like the 2017 Equifax data breach but its not time to lose
calm and understand the impact and whether your app is affected or not and
what you can do in short term to prevent it.
But first, let's see what is the issue itself
Log4j2
is a logging library that is used to log messages. Since Java is the most
popular server-side programming language and logging is a must in
server-side apps, Log4j has been used widely and holds the title of the most popular logging library for Java developers. I myself have used log4j in many projects.
The problem is that it also supports formatted string and there is one format that instructs Log4j to download a class from a remote server using LDAP protocol which can be used to execute remote code and cause this zero-day vulnerability.
I know, you might be thinking what? Why does Log4j need to download a class and yes, that puzzled me and many others but that's the reality and we will earn more about the issue and its tactical and strategic solution in this article.
What exactly is the Log4j2 issue and RCE Vulnerability?
The Job of a logging library is to write messages to the destination, it
could be a file or a database. Over the year, logging evolved and most of
the time your logging message is not a simple message but a message with
variables something like
Logger.log("This message is from {username}");
Yes, I am talking about placeholders that are resolved at runtime.
Log4j has a magical feature that allows it to look up into a remote server
to resolve such variables (well, I didn't know about that feature before,
just got to know about it due to the issue).
Now, this feature not only looks to resolve content from a remote server,
which could be a bad or evil server but also it doesn't sanitize the value
it receives.
For example, you would expect that
Logger.log("This message is from {username}") the username variable will be sanitized to remove any special character and
treat it as text rather than code but Log4j2 doesn't do that.
It's very similar to SQL injection which is told to us but in this case,
even the solution of SQL injection is causing Log injection. I mean, when I
learned SQL injection I understand that string concatenation is bad and you
should use
PreparedStatement and Placeholders to sanitize user input before sending it to the
database.
I mean
Logger.log("This message is from" + username) ; // This was bad
Logger.log("This message is from {username}") // This was good
// but it's not good in the case of Log4j2.
Due to this, we are not facing the vulnerability which will impact many Java
applications but only if they are externally exposed.
Who is impacted by the Log4j2 issue?
As per my research, anyone using the Log4j version greater than 2.0 and less
than or equal to Log4j 2.14.1 are impacted. This is triggered if you are
using formatted string for logging becuase in this version the remote lookup
feature is by default enabled.
But, in order to take advantage of this feature hackers need to have control
of your app which they can gain if you have any TCP, HTTP, or REST endpoints
and also if you are logging user input into a log using Log4j versions which
have this vulnerability.
This means:
1. If your app doesn't have any endpoints then it's not impacted
2. If it's running on Log4j1.x then it's not impacted
3. If your app is running on JDK versions greater than 6u211, 7u201, 8u191,
and 11.0.1 then they are not affected because in these versions
com.sun.jndi.ldap.object.trustURLCodebase is set to false meaning JNDI
cannot load remote code using LDAP.
However, there could be more ways to target this vulnerability that can
result in RCE. For example, an attacker could still leverage existing
code on the server to execute a payload. An attack targeting the class
org.apache.naming.factory.BeanFactory, present on Apache Tomcat servers can be possible, as discussed
here.
How to solve this Lo4j2 RCE issue?
The permanent but non-trivial solution is to upgrade to a Log4j2 version
that doesn't have this vulnerability. For example Version 2.15.0 of
log4j has been released without the vulnerability. log4j-core.jar is
available on Maven Central which you can download and upgrade.
But if you are running anywhere close to the real-world system then you know
that it's a non-trivial exercise and you may be required to update a couple
of other libraries.
The other solution suggested by CVE website is to disable this feature by
settin gup system property
"log4j2.formatMsgNoLookups"
to true; or by removing the
JndiLookup class from the classpath (example:
zip -q -d log4j-core-*.jar
org/apache/logging/log4j/core/lookup/JndiLookup.class).
You can also upgradde Java version to higher version where this lookup is
not allowed. For example, Java versionn 8u121 protects against remote code
execution by defaulting
"com.sun.jndi.rmi.object.trustURLCodebase"
and
"com.sun.jndi.cosnaming.object.trustURLCodebase"
to "false".
2. Alternative solution using SLF4j and Logbak
There is another way to solve the problem by replacing Log4j2 with SLF4J and then using LogBak. If you remember SLF4j is just an API that provides an abstraction over logging API and the main advantage of using SLF4j is that you can replace the underlying logging library without changing the code. I mean you can replace the underlying library Log4j2 with Logbak which doesn't have this vulnerability.
If you remember, I advised long back that why Java developers should use SLF4j over log4j but at that time I didn't think that this step can be so useful.
In case, if you are not using SLF4j then you may or may not require some code changes. At first, you should just try to replace the log4j JAR with an SLF4j jar and replace the config with a Logbak config (XML) and see if it works.
And, here is a nice diagram that explains how Log4j can run the remote code:
That's all about this
Log4j2 RCE vulnerability issue and how to deal with it, The situation
is still evolving as it's gaining more and attention. I will update this
article with more info as and when I get but there is a lot of content
already available on the web if you are want to learn more.
Further Learning
Here are the links for some of the useful posts I found on this Log4j2
issue:
1. THis HackerNews thread -
https://news.ycombinator.com/item?id=29504755
2. Lunasec' Log4Shell: RCE 0-day exploit found in log4j 2,
https://www.lunasec.io/docs/blog/log4j-zero-day/
3. CVE page where this issue is tracked -
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44228
4. Blog post on Sonatype blog - Critical New 0-day Vulnerability in Popular
Log4j Library Discovered with Evidence of Mass Scanning for Affected
Applications
https://blog.sonatype.com/a-new-0-day-log4j-vulnerability-discovered-in-the-wild
5. CVE-2021-44228 - Log4j RCE 0-day mitigation on CloudFlare blog
- https://blog.cloudflare.com/cve-2021-44228-log4j-rce-0-day-mitigation/
If you find more information about the impact and any other quick way to
solve this problem, feel free to share in the comments. This is the most
widely impacted vulnerability issue I have seen in my career as a Java
developer and I am sure I am not alone.
No comments:
Post a Comment