Première implémentation d'exploit partagée publiquement pour CVE-2026-33439 (RCE OpenAM avant authentification via la déserialisation de jato.clientSession).
Analyse humaine + analyse assistée par IA + rétro-ingénierie + avis → exploit
Première implémentation d'exploit partagée publiquement pour CVE-2026-33439
Vulnérabilité de désérialisation Java non authentifiée dans ForgeRock OpenAM permettant une exécution de code à distance complète via des objets de session JATO façonnés. La même rivière coule deux fois : ils ont corrigé jato.pageSession (CVE-2021-35464) et oublié jato.clientSession (CVE-2026-33439). Une chaîne de gadgets de désérialisation ne demande pas d'identifiants.
CVE-2026-33439 est une vulnérabilité d'exécution de code à distance pré-authentification dans OpenIdentityPlatform OpenAM (versions antérieures à 16.0.6). La vulnérabilité provient d'une désérialisation Java non sécurisée du paramètre HTTP jato.clientSession dans ClientSession.deserializeAttributes(), qui appelle Encoder.deserialize() → ApplicationObjectInputStream.readObject() sans liste blanche de classes appliquée.
Un attaquant non authentifié envoie une requête HTTP GET ou POST façonnée contenant un objet Java sérialisé à n'importe quel point de terminaison JATO ViewBean dont le JSP rend les balises <jato:form>. À la réception, le serveur désérialise l'objet sans validation, déclenchant une chaîne de gadgets entièrement construite à partir de classes groupées dans le WAR OpenAM - aucune bibliothèque externe requise - et exécute des commandes OS arbitraires en tant qu'utilisateur du processus applicatif.
Vecteur CVSS 4.0 : AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N → 9.3 Critique
Vecteur CVSS 3.1 : AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H → 9.8 Critique
Cette vulnérabilité est une régression directe du correctif incomplet appliqué après CVE-2021-35464.
CVE-2021-35464 (ForgeRock AM / OpenAM) : RCE pré-authentification via désérialisation non sécurisée du paramètre jato.pageSession. Largement exploitée dans la nature ; inscrite sur la liste KEV de la CISA. Le correctif a introduit WhitelistObjectInputStream dans ConsoleViewBeanBase.deserializePageAttributes() - une sous-classe personnalisée d'ObjectInputStream qui vérifie chaque nom de classe par rapport à une liste blanche codée en dur d'environ 40 classes sûres avant de l'instancier.
CVE-2026-33439 (OpenAM ≤ 16.0.5) : Le correctif n'a été appliqué qu'à jato.pageSession. Le paramètre jato.clientSession - géré par un chemin de code complètement séparé dans ClientSession.deserializeAttributes() - n'a jamais été corrigé et utilise toujours Encoder.deserialize() → ApplicationObjectInputStream non filtré, qui appelle ObjectInputStream.readObject() sans liste blanche de classes.
La primitive d'attaque est la même. Le puits de désérialisation est différent. Seul le nom du paramètre a changé.
JATO sérialise l'état de la vue UI dans des paramètres HTTP nommés jato.pageSession et jato.clientSession. Lorsqu'une requête arrive, OpenAM désérialise ces paramètres pour restaurer l'état de l'UI avant de rendre la réponse. Les deux paramètres suivent des chemins de code entièrement différents.
Le chemin de code corrigé (post-CVE-2021-35464) pour jato.pageSession :```java // PATCHED - ConsoleViewBeanBase.deserializePageAttributes() ObjectInputStream ois = new WhitelistObjectInputStream(new ByteArrayInputStream(decoded)); // class whitelist enforced - gadget chains blocked Object obj = ois.readObject();
Le chemin de code non corrigé pour jato.clientSession (vulnérable) :```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() construit un simple ApplicationObjectInputStream — une sous-classe de ObjectInputStream sans filtrage de classes. Toute classe présente sur le classpath de la JVM peut être instanciée. La désérialisation est déclenchée lors du rendu JSP chaque fois qu'une balise < jato:form > est rendue :``` getClientSession() → hasAttributes() → getEncodedString() → isValid() → ensureAttributes() → deserializeAttributes()
---
<div id="vulnerability_affected"/>
### ***Versions concernées***
| Produit | Vulnérable | Corrigé |
|--------------------------------|--------------------------------------------------|---------|
| OpenIdentityPlatform OpenAM | ≤ 16.0.5 | 16.0.6 |
| ForgeRock AM (downstream) | Potentiellement concerné selon la lignée de correctifs | - |
---
<div id="vulnerability_attacksurface"/>
### ***Surface d'attaque***
Tout endpoint JATO ViewBean dont le JSP contient une balise *< jato:form >* est exploitable sans authentification :
| Endpoint | Objectif |
|---------------------------|---------------------------------------|
| /ui/PWResetUserValidation | Réinitialisation du mot de passe – saisie de l'identité utilisateur |
| /ui/PWResetQuestion | Réinitialisation du mot de passe – questions de sécurité |