OpenAM Pre-Authentication RCE via `jato.clientSession` Deserialization (CVE-2026-33439)
by Ibonok (nuclei template author: ibonok) · 2026-07-05
- 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
References
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-05 |
| Last Updated | 2026-04 |
| Author / Researcher | Ibonok (nuclei template author: ibonok) |
| CVE / Advisory | CVE-2026-33439 |
| Category | web |
| Severity | Critical |
| CVSS Score | 9.8 (per bundled nuclei template) |
| Status | Weaponized |
| Tags | openam, forgerock, deserialization, rce, pre-auth, java, gadget-chain, xalan, jato |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | ForgeRock / OpenIdentityPlatform OpenAM |
| Versions Affected | OpenAM versions prior to the fix in commit 014007c63cacc834cc795a89fac0e611aebc4a32 |
| Language / Platform | Java (JDK 11+ to build/run the exploit; targets a Java-based OpenAM server) |
| Authentication Required | No |
| Network Access Required | Yes |
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
- Generate a serialized gadget-chain payload (
PriorityQueue+ Click1 + XalanTemplatesImpl) whose translet bytecode invokesRequestManager.getRequestContext()to reach the live JATO request/response objects. - Encode the payload in OpenAM’s expected format (
\x00prefix + URL-safe Base64, no padding). - Send the payload as the
jato.clientSessionquery parameter to an unauthenticated Password Reset endpoint, e.g./sso/ui/PWResetUserValidation, with the command to execute supplied via a customcmdHTTP header. Encoder.deserialize()deserializes the payload with no filtering, instantiating the gadget chain; the translet reads thecmdheader, runs it withsh -c, and writes stdout/stderr straight into the HTTP response body.- 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.javaandbuild.shin this folder, plus the bundled nuclei templateCVE-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 bybuild.sh/MANIFEST.MFbut were not mirrored here (standard public Maven artifacts) — fetch them separately into alib/directory before building.
| |
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
cmdHTTP header and an oversizedjato.clientSessionvalue - OpenAM process spawning shell children (
sh -c ...) not attributable to normal application behavior - Command output (e.g.
/etc/passwdcontents,id/unameoutput) appearing in HTTP response bodies from Password Reset pages
Remediation
| Action | Detail |
|---|---|
| Primary fix | Apply OpenAM commit 014007c63cacc834cc795a89fac0e611aebc4a32, which adds a class filter to the ObjectInputStream used in SessionEncodeURL.readSessionID() |
| Interim mitigation | Block/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.
| |