Primera implementación de exploit compartida públicamente para CVE-2026-33439 (RCE pre-autenticación en OpenAM mediante deserialización de jato.clientSession).
Conocimiento humano + análisis asistido por IA + ingeniería inversa + aviso → exploit
Primera implementación de exploit compartida públicamente para CVE-2026-33439
Vulnerabilidad de deserialización de Java sin autenticación en ForgeRock OpenAM que permite la ejecución remota de código completa mediante objetos de sesión JATO manipulados. El mismo río fluye dos veces: parchearon jato.pageSession (CVE-2021-35464) y olvidaron jato.clientSession (CVE-2026-33439). Una cadena de gadgets de deserialización no pide credenciales.
CVE-2026-33439 es una vulnerabilidad de ejecución remota de código (RCE) previa a la autenticación en OpenIdentityPlatform OpenAM (versiones anteriores a 16.0.6). La vulnerabilidad se origina en la deserialización no segura de Java del parámetro HTTP jato.clientSession dentro de ClientSession.deserializeAttributes(), que llama a Encoder.deserialize() → ApplicationObjectInputStream.readObject() sin aplicar ninguna lista blanca de clases.
Un atacante no autenticado envía una solicitud HTTP GET o POST manipulada que contiene un objeto Java serializado a cualquier endpoint JATO ViewBean cuyo JSP renderice etiquetas <jato:form>. Al recibirla, el servidor deserializa el objeto sin validación, activando una cadena de gadgets construida íntegramente con clases incluidas en el WAR de OpenAM, sin necesidad de librerías externas, y ejecuta comandos arbitrarios del sistema operativo como el usuario del proceso de la aplicación.
CVSS 4.0 Vector: AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N → 9.3 Crítico
CVSS 3.1 Vector: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H → 9.8 Crítico
Esta vulnerabilidad es una regresión directa del parche incompleto aplicado después de CVE-2021-35464.
CVE-2021-35464 (ForgeRock AM / OpenAM): RCE previa a la autenticación mediante deserialización no segura del parámetro jato.pageSession. Ampliamente explotado en el mundo real; incluido en la lista KEV de CISA. El parche introdujo WhitelistObjectInputStream dentro de ConsoleViewBeanBase.deserializePageAttributes(), una subclase personalizada de ObjectInputStream que comprueba cada nombre de clase contra una lista blanca codificada de ~40 clases seguras antes de instanciarla.
CVE-2026-33439 (OpenAM ≤ 16.0.5): El parche se aplicó solo a jato.pageSession. El parámetro jato.clientSession, gestionado por una ruta de código completamente separada en ClientSession.deserializeAttributes(), nunca fue parcheado y sigue utilizando Encoder.deserialize() → ApplicationObjectInputStream sin filtrar, que llama a ObjectInputStream.readObject() sin ninguna lista blanca de clases.
La primitiva de ataque es la misma. El sumidero de deserialización es diferente. Solo cambió el nombre del parámetro.
JATO serializa el estado de la vista de la interfaz de usuario en parámetros HTTP llamados jato.pageSession y jato.clientSession. Cuando llega una solicitud, OpenAM deserializa estos parámetros para restaurar el estado de la interfaz antes de renderizar la respuesta. Los dos parámetros siguen rutas de código completamente diferentes.
La ruta de código parcheada (post-CVE-2021-35464) para jato.pageSession:```java // PATCHED - ConsoleViewBeanBase.deserializePageAttributes() ObjectInputStream ois = new WhitelistObjectInputStream(new ByteArrayInputStream(decoded)); // class whitelist enforced - gadget chains blocked Object obj = ois.readObject();
La ruta de código sin parchear para jato.clientSession (vulnerable):```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() construye un ApplicationObjectInputStream simple: una subclase de ObjectInputStream sin filtrado de clases. Cualquier clase en el classpath de la JVM puede ser instanciada. La deserialización se activa durante el renderizado de JSP cada vez que se renderiza una etiqueta < jato:form >:``` getClientSession() → hasAttributes() → getEncodedString() → isValid() → ensureAttributes() → deserializeAttributes()
---
<div id="vulnerability_affected"/>
### ***Versiones afectadas***
| Producto | Vulnerable | Corregido |
|-----------------------------|-------------------------------------------------|--------|
| OpenIdentityPlatform OpenAM | ≤ 16.0.5 | 16.0.6 |
| ForgeRock AM (downstream) | Potencialmente afectado según el linaje de parches | - |
---
<div id="vulnerability_attacksurface"/>
### ***Superficie de ataque***
Cualquier endpoint de JATO ViewBean cuyo JSP contenga una etiqueta *< jato:form >* es explotable sin autenticación previa:
| Endpoint | Propósito |
|---------------------------|--------------------------------------|
| /ui/PWResetUserValidation | Restablecimiento de contraseña - entrada de identidad del usuario |
| /ui/PWResetQuestion | Restablecimiento de contraseña - preguntas de seguridad |