
공격적 보안 연구자 + AI vs. 신규 n-day: 어느 금요일 밤에 CVE-2026-53435에 대한 최초의 공개 PoC를 구축. 내부에 Raw 8h20m 로그 포함.
최초 공개 개념 증명 for CVE-2026-53435, 기존에는 권고만 존재하고 어디에도 PoC가 공개되지 않은 상태에서 작성되었습니다. 모호한 한 줄짜리 권고로부터 약 8.5시간 동안 금요일 밤에 재구성되었습니다. — 익스플로잇을 직접 작성하는 것이 아니라, AI를 지시하여 막다른 길, 방향 전환, 검증을 거쳐 작동하는 체인이 나올 때까지 진행했습니다.

PoC가 컨트롤러에서 /etc/passwd에 접근 — 임의 파일 읽기 확인됨
| CVE | CVE-2026-53435 (Jenkins SECURITY-3707) |
| 분류 | 안전하지 않은 역직렬화 (config.xml을 통한 ClassFilter 우회) |
| 영향 (이 PoC) | 인증된 사용자의 컨트롤러에서 임의 파일 읽기 |
| 영향받는 버전 | Jenkins weekly ≤ 2.567, LTS ≤ 2.555.2 |
| 수정 버전 | Jenkins weekly 2.568, LTS 2.555.3 |
| 권고문 | https://www.jenkins.io/security/advisory/2026-06-10/ (2026-06-10 게시) |
| 작성 시점 상태 | 공개된 PoC 없음 (GitHub PoC 저장소: 0) |
이는 결과물뿐만 아니라 과정을 보여주는 실험입니다.
수년 동안 공격 연구자의 결과물은 완성된 익스플로잇 하나뿐이었습니다. 그것을 만드는 데 들인 8시간의 잘못된 방향 전환은 사라졌습니다. 이 저장소는 그 잘못된 방향을 유지합니다. 사람과 AI가 새로운 n-day를 권고문에서 작동하는 PoC로 만드는 과정의 전체, 가볍게 편집된 기록이 부록으로 포함되어 있습니다.
이것이 제시하는 요점은 의도적으로 'AI가 해냈다'가 아닙니다. 8시간은 그렇지 않았다는 증거입니다. AI는 체인을 한 번에 완성하지 못했습니다. 작업을 이끈 것은 도메인 전문 지식이었습니다. — 권고문에 역직렬화 싱크가 숨겨져 있다는 점, Jenkins 코어 타입에서 찾아야 한다는 점, 패치 전의 DescribableList가 요소 타입을 강제하지 않는다는 점, 주장을 신뢰하는 대신 검증하는 방법을 아는 점 등입니다. 연구자의 가치는 사라지지 않았습니다. 그것은 익스플로잇을 입력하는 것에서 조종, 가지치기, 검증으로 이동했습니다.
그 변화가 바로 문서화할 가치가 있는 것입니다.
Jenkins는 사용자 정의 ClassFilter로 역직렬화를 보호하며, 이 필터는 Jenkins 코어 또는 플러그인에 정의된 타입만 허용합니다. CVE-2026-53435는 이것만으로는 충분하지 않다는 점입니다. config.xml을 POST할 수 있는 공격자는 Jenkins가 임의의 코어/플러그인 타입을 예상치 못한 컨텍스트로 역직렬화하도록 한 후, Stapler 라우팅을 통해 HTTP로 해당 객체에 접근할 수 있습니다.
이 PoC는 hudson.Plugin$DummyImpl (Jenkins 코어 타입이므로 위치 화이트리스트를 통과함)을 ListView의 <properties> 목록에 심습니다. 이 목록은 패치 전에는 요소 타입을 강제하지 않는 DescribableList<ViewProperty>입니다. 심어진 객체는 baseResourceURL=file:/을 가지고 있습니다. 여기에 HTTP 요청을 라우팅하면 컨트롤러의 파일 시스템에서 직접 파일을 제공합니다.
일반적인 ysoserial 체인은 여기서 작동하지 않습니다. 가젯은 필터를 통과하기 위해 Jenkins/플러그인 상주 타입이어야 합니다. 그 제약이 핵심입니다.
소유하거나 명시적으로 테스트 권한이 있는 시스템에만 사용하십시오.
익스플로잇은 동일한 구성의 두 컨테이너(취약한 2.555.2 및 패치된 2.555.3)에서 실행되어 이 CVE를 활용하는 것이지 관련 없는 파일 읽기 프리미티브가 아님을 확인했습니다:
패치된 빌드는 요청을 수락하지만, 수정 사항이 역직렬화 시간에 심어진 타입을 거부하므로 속성 목록이 비어서 라우팅할 대상이 없습니다. 실패는 정확히 권고문이 설명하는 메커니즘에서 발생합니다. 이것이 이 PoC를 CVE-2026-53435의 진정한 PoC로 만드는 이유입니다.
python3 exploit_cve_2026_53435_v2.py <base_url> <user> <pass> <remote_file> [view_name]
# example (against your own lab):
python3 exploit_cve_2026_53435_v2.py http://127.0.0.1:8080 <user> <pass> /etc/passwd
base_url — 대상의 http://host:port (일반 HTTP; 인스턴스가 실제로 TLS를 종료하지 않는 한 https를 접두사로 붙이지 마십시오.)config.xml을 POST할 수 있는 권한(View/Configure)과 Overall/Read 권한이 있는 계정이 필요합니다.docker compose -f lab/docker-compose.yml up -d
# vulnerable: http://127.0.0.1:8080 (Jenkins LTS 2.555.2)
# patched: http://127.0.0.1:8081 (Jenkins LTS 2.555.3, negative control)
랩은 Groovy init을 통해 로컬 전용 사용자 데이터베이스를 프로비저닝하여 외부 IdP 없이 인증된 낮은 권한 경로를 실행할 수 있습니다.
2026-06-12 (Fri) 15:00 → 23:23 ≈ 8h 20m
15:00–15:12 랩 구축 (docker: vuln 2.555.2 / patched 2.555.3) + 첫 정찰
15:12–21:00 역직렬화 싱크 및 가젯 분석
(Commons-Collections 우회 시도 실패 → pivot
from properties to actions and back)
21:00–22:30 ClassFilter 분석 + 가젯 재탐색, 코어 타입으로 제한
22:30–23:00 작동 PoC (v1 → v2) + 차등 검증 (취약 vs 패치됨)
그 시간의 대부분은 입력이 아닌 분석이었습니다. 익스플로잇 자체는 마지막 약 30분 동안 완성되었습니다. 올바른 싱크와 가젯이 알려지자마자였습니다.
Claude Code(Anthropic)로 구축되었으며, 작성자가 대화식으로 진행했습니다:
완전하고 가볍게 편집된 작업 기록은 transcript/에 있습니다. — 막다른 길을 포함하여 원시 상태로 유지되었습니다. (몇 줄의 어조를 부드럽게 하고 로컬 네트워크 세부 정보를 숨기기 위해 편집되었습니다. 기술적인 내용은 제거되지 않았습니다.)
승인된 보안 테스트, 연구 및 교육 목적으로만 사용하십시오. 작성자와 기여자는 오용에 대한 책임을 지지 않습니다. 대상 취약점은 패치되었습니다. Jenkins LTS 2.555.3 / weekly 2.568 이상으로 업데이트하십시오.
| 2.555.2 (취약) | 2.555.3 (패치됨) |
|---|
createView | HTTP 200 | HTTP 200 |
저장된 <properties> | <hudson.Plugin_-DummyImpl/> — 유지됨 | <properties/> — 제거됨 |
트리거 → /etc/passwd | root:x:0:0:... — 읽기 성공 | 비어 있음 — 차단됨 |