All the headlines for the past week have touched upon the "Log4Shell" bug, CVE-2021-44228. This is a "big deal" bug that's coupled with some surprising features of how Java works.
Before we get into the news roundup portion of this, we need to discuss a little history. Today, the buzzword is "microservices". We break up our large, complicated application into a bunch of tiny services, and focus on how messages travel between these services. Usually, these services are communicating through some sort of network protocol or a message bus. The topology of a large and complicated application can turn into a forest of unclear and difficult to parse dependencies.
Way back in the "J2EE" days of Java, we wanted to create the same complexity. Instead of "services" we had "beans", which were services with a stupid name. And, since each bean represented an object, it was also supposed to be single purpose. So basically, the idea was to build microservices but in this weird Java ecosystem where everything got configured (circa the early 2000s) via giant piles of XML files.
There was a problem here, though: if you were going to distribute your application across a bunch of different servers and nodes, you needed a way to find the various components you depended on. How do you find your beans?
Enter the Java Naming and Directory Interface, JNDI. This allows an application module to say, "hey, I need a thing called com.mysite.BeanIsaCoffeePunService
", and then JNDI can go find where that is in your application architecture. But managing a directory service is one of those things that can get extra complicated, so JNDI won't just talk to various Java application servers, it can go and call out to LDAP, DNS, or even the filesystem to resolve your requests.
Java's enterprise frameworks have matured around this complexity, and generally most developers don't have to worry about these details. Because of the "bureaucratic" nature of enterprise Java code, it tends to be popular in very bureaucratic environments like finance companies or insurance. And with that we can start talking about the Log4Shell vulnerability.
XKCD already published a quick summary a few years ago:
One of the ways in which Java's frameworks have matured is that they all use a common logging module: Log4j. Log4j is an Apache project, and it's integrated into basically everything Java. Many programs that write log files either uses Log4j directly or uses an Apache project that uses it. And it has a remote code execution vulnerability.
Specifically, the RCE ties into Log4j's string interpolation features. If a string sent to the logger contains ${someVar}
, it will try and evaluate that expression. If it contains ${jndi://…}
, it will also try and evaluate that expression, by doing a JNDI lookup. And as you recall, JNDI can talk to LDAP. Which means:
A story in three parts 😶 #log4j pic.twitter.com/XMl02BcaJY
— Cas van Cooten (@chvancooten) December 10, 2021
You can make Apple's iCloud servers call out to your own LDAP server simply by changing the name of your iPhone to an appropriate string.
That's a harmless example of the vulnerability, but even that should be scary: by controlling the strings that get logged, I can make your server call out across the Internet to a server I control. But it's much, much worse than that.
How much worse? If the response from the LDAP server is a Java .class
file, the victim will execute that code. That's right, a maliciously formatted string that gets passed to the logger can reach out across the Internet, download malicious code, and execute that code as part of writing out your log message.
Which means, yes, definitely ransomware attacks are happening. That one's at a payroll company, but there were a lot of places that were vulnerable, and the exploit was in the wild before being reported. And it's being widely exploited. It's serious, and represents a good example of an ongoing threat that will likely need process changes to prevent in future projects.
Now, Log4j has patched this bug, and there are also configuration options which can disable this behavior in older versions. But getting everyone on the planet to upgrade or fix is one of those unlikely tasks. So of course, there's Logout4Shell, which uses the exploit to close the hole on target servers.
Given the scope of the flaw, however, not only will there be extended fallout from it, but it also forces the tech community to confront the relationship between businesses and OpenSource. A lot of unpaid labor goes into making Log4j work, and while companies might throw some token funding at these large projects, "no company pays their law firm on Patreon". Much of the world silently uses Open Source software as part of doing business, often at no cost. When events like this happens, it highlights how important this software is. And if it's important, we may need to have some conversations about how it gets made, how it gets funded, and how we think about its role.
For now, at least, there's a patch. The consequences will linger, certainly, but what we really should be thinking about is what the next one of these is going to be? The part of an iceberg above the waterline is the smallest portion- what else lurks beneath the surface?