最近几周(2025年11月),pdfminer.six 中披露了一个有趣的漏洞(CVE-2025-64512),这是一个用于处理 PDF 文件的流行 Python 项目,尤其在 AI 管道中被使用。该漏洞通过 pickle.loads() 反序列化不受信任的数据,并利用 PDF 文件作为攻击向量,从而实现远程代码执行。事情到此为止:这是在一个流行的 Python 包中一个重要的漏洞。但引起我注意的是它的可利用性 👀。
在类 Linux 系统上,只能解析文件系统中的文件。攻击者需要提供恶意 PDF 文件供处理,并且恶意 pickle 文件必须已经存在于目标系统的某个已知位置,因为该路径需要在 PDF 文件本身中设置。在许多情况下,这将很难利用,因为即使攻击者同时提供了 PDF 和 pickle 文件,也无法事先知道 pickle 文件的完整路径。……总体而言,在 Linux 或类 Linux 系统上风险较低。
因此,显然,要在类 Linux 系统上利用此漏洞,攻击者需要:
我们能否创建一个有效的 PDF 文件,在不了解恶意 pickle 文件路径的情况下触发漏洞?
“有效”意味着 pdfminer.six 不会拒绝该文件并开始处理它(因为 PDF 文件就是 PDF 阅读器打开的文件)。
答案是可以,创建一个混合型载荷(polyglot payload)(某种意义上的)。思路是创建一个文件,它既是有效的 pickle.gz 文件,又是有效的 PDF 文件,这样 pdf2txt.py 可以开始处理一个 PDF 文件,然后指向它,以 GZIP 格式加载 pickle 代码。
通常——但_并非总是_ 🥲——如果一个文件在某个位置包含 %PDF-,通常是在前 1024 字节内(1 - 2),那么它就是 PDF 文件。对于 pdfminer.six,一个有效的 PDF 文件只需包含一个 /Root 对象(pdfdocument.py#L752)。
GZIP 文件有特定的起始字节(RFC 1952 - Sec. 2.3.1),但它支持注释(FCOMMENT,RFC 1952 - Sec. 2.3.1)。
因此,混合型文件的设计如下:创建一个包含恶意 pickle 载荷的有效 GZIP 文件,并在 GZIP 的 FCOMMENT 标志中嵌入一个有效的 PDF 文件。然后使用该文件作为有效的 PDF 文件,通过 pdf2txt.py 触发漏洞,并使用同一个文件来执行恶意 pickle。
(2025.12.12)编辑:
我们唯一限制是文件名:必须以 .pickle.gz 结尾(这嵌入在 pdfminer.six 代码中,cmapdb.py#L235)。
我们有两个限制:
pdfminer.six 代码中,cmapdb.py#L235);我有点惊讶这个 CVE 被如此低估,考虑到这个项目的受欢迎程度(GitHub 上有 6k ⭐️,但根据 GitHub 统计数据,被 34k 个项目使用)以及其使用场景(命令行工具、AI 工作流、管道——简而言之,所有你不想因为运行正常就去更新的基础设施)。
例如,微软工具 markitdown 0.1.3(microsoft/markitdown,GitHub 上 84k ⭐️,被 2k 个项目使用),如果在 12 月 1 日之前安装,就会因为 pdfminer.six 而容易受到任意代码执行攻击。微软团队在 12 月 1 日发布了补丁 0.1.4,但没有安全警报,所以我认为其他工程团队并没有优先考虑更新。
其他项目可能也受到 CVE-2025-64512 的影响,而且利用起来相当容易。
(不完整的)受影响项目列表:
docker build -t cve-2025-64512-poc .
docker run --rm -it cve-2025-64512-poc
pdf2txt.py payload.pickle.gz
docker build -t cve-2025-64512-poc .
docker run --rm -it cve-2025-64512-poc
markitdown markitdown-payload.pickle.gz -x pdf -o output.md
