Erste öffentlich geteilte Exploit-Implementierung für CVE-2026-33439 (OpenAM Pre-Auth-RCE über jato.clientSession-Deserialisierung).
Menschliche Einsicht + KI-gestützte Analyse + Reverse Engineering + Advisory → Exploit
Erste öffentlich geteilte Exploit-Implementierung für CVE-2026-33439
Java-Deserialisierungsschwachstelle in ForgeRock OpenAM ohne Authentifizierung, die über manipulierte JATO-Sitzungsobjekte vollständige Remote-Code-Ausführung ermöglicht. Derselbe Fluss fließt zweimal: Sie haben jato.pageSession (CVE-2021-35464) behoben und jato.clientSession (CVE-2026-33439) vergessen. Eine Deserialisierungs-Gadget-Kette fragt nicht nach Anmeldedaten.
CVE-2026-33439 ist eine Remote-Code-Execution-Schwachstelle vor der Authentifizierung (Pre-Auth) in OpenIdentityPlatform OpenAM (Versionen vor 16.0.6). Die Schwachstelle resultiert aus unsicherer Java-Deserialisierung des HTTP-Parameters jato.clientSession innerhalb von ClientSession.deserializeAttributes(), wobei Encoder.deserialize() → ApplicationObjectInputStream.readObject() ohne Anwendung einer Klassen-Whitelist aufgerufen wird.
Ein nicht authentifizierter Angreifer sendet eine manipulierte HTTP-GET- oder HTTP-POST-Anfrage mit einem serialisierten Java-Objekt an einen beliebigen JATO-ViewBean-Endpunkt, dessen JSP <jato:form>-Tags rendert. Beim Empfang deserialisiert der Server das Objekt ohne Validierung, löst eine Gadget-Kette aus, die vollständig aus den im OpenAM-WAR gebündelten Klassen besteht - ohne dass externe Bibliotheken erforderlich sind - und führt beliebige Betriebssystembefehle als Benutzer des Anwendungsprozesses aus.
CVSS 4.0 Vektor: AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N → 9.3 Kritisch
CVSS 3.1 Vektor: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H → 9.8 Kritisch
Bei dieser Schwachstelle handelt es sich um eine direkte Regression infolge der unvollständigen Korrektur, die nach CVE-2021-35464 angewendet wurde.
CVE-2021-35464 (ForgeRock AM / OpenAM): Pre-Auth-RCE über unsichere Deserialisierung des Parameters jato.pageSession. In freier Wildbahn weit verbreitet ausgenutzt; in der CISA-KEV-Liste enthalten. Die Korrektur führte WhitelistObjectInputStream in ConsoleViewBeanBase.deserializePageAttributes() ein - eine benutzerdefinierte ObjectInputStream-Unterklasse, die vor der Instanziierung jeden Klassennamen gegen eine fest codierte Zulassungsliste von ~40 sicheren Klassen prüft.
CVE-2026-33439 (OpenAM ≤ 16.0.5): Die Korrektur wurde nur auf jato.pageSession angewendet. Der Parameter jato.clientSession - der über einen völlig getrennten Codepfad in ClientSession.deserializeAttributes() verarbeitet wird - wurde nie gepatcht und verwendet weiterhin das ungefilterte Encoder.deserialize() → ApplicationObjectInputStream, das ObjectInputStream.readObject() ohne Klassen-Whitelist aufruft.
Die Angriffsprimitive ist dieselbe. Das Deserialisierungs-Sink ist ein anderes. Nur der Parametername hat sich geändert.
JATO serialisiert den UI-Ansichtszustand in die HTTP-Parameter jato.pageSession und jato.clientSession. Wenn eine Anfrage eintrifft, deserialisiert OpenAM diese Parameter, um den UI-Zustand wiederherzustellen, bevor die Antwort gerendert wird. Die beiden Parameter folgen völlig unterschiedlichen Codepfaden.
Der gepatchte Codepfad (nach CVE-2021-35464) für jato.pageSession:```java // PATCHED - ConsoleViewBeanBase.deserializePageAttributes() ObjectInputStream ois = new WhitelistObjectInputStream(new ByteArrayInputStream(decoded)); // class whitelist enforced - gadget chains blocked Object obj = ois.readObject();
Der ungepatchte Codepfad für jato.clientSession (verwundbar):```java
// ClientSession.java
protected ClientSession(RequestContext context) {
this.encodedSessionString =
context.getRequest().getParameter("jato.clientSession");
}
protected void deserializeAttributes() {
if (this.encodedSessionString != null
&& this.encodedSessionString.trim().length() > 0) {
this.setAttributes(
(Map) Encoder.deserialize(
// VULNERABLE - URL-safe base64 decode then plain ObjectInputStream
Encoder.decodeHttp64(this.encodedSessionString), false)
);
}
}
Encoder.deserialize() erstellt ein einfaches ApplicationObjectInputStream – eine Unterklasse von ObjectInputStream ohne Klassenfilterung. Jede Klasse auf dem JVM-Klassenpfad kann instanziiert werden. Die Deserialisierung wird während des JSP-Renderings ausgelöst, sobald ein < jato:form >-Tag gerendert wird:``` getClientSession() → hasAttributes() → getEncodedString() → isValid() → ensureAttributes() → deserializeAttributes()
---
<div id="vulnerability_affected"/>
### ***Betroffene Versionen***
| Produkt | Verwundbar | Behoben |
|-----------------------------|-------------------------------------------------|---------|
| OpenIdentityPlatform OpenAM | ≤ 16.0.5 | 16.0.6 |
| ForgeRock AM (Downstream) | Möglicherweise betroffen, abhängig von der Patch-Historie | - |
---
<div id="vulnerability_attacksurface"/>
### ***Angriffsfläche***
Jeder JATO-ViewBean-Endpunkt, dessen JSP ein *< jato:form >*-Tag enthält, ist ohne Authentifizierung ausnutzbar:
| Endpunkt | Zweck |
|----------------------------|--------------------------------------------|
| /ui/PWResetUserValidation | Passwort-Reset – Eingabe der Benutzeridentität |
| /ui/PWResetQuestion | Passwort-Reset – Sicherheitsfragen |