pypdf一个PDF吃光内存,CVE-2026-119204"

admin 2026-11-01 18:09:43 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

pypdf 一个 PDF 吃光内存,CVE-2026-119204

红队安全圈
红队安全圈

红队安全圈

2026年10月31日 09:25
重庆

去阅读

pypdf 展开页面树时没有全文档条目上限,一份共享页面被反复引用的 PDF 就能让内存按引用次数成倍膨胀,直到进程 OOM。

pypdf 是 Python 里最常用的纯 Python PDF 库,上传解析、文本提取、发票和简历识别、RAG 文档加载器都在用它。这类解析器被喂了恶意文件,出的问题往往不是拿到 shell,而是服务直接被打挂。10 月 28 日发布的 6.21.4 一口气修了三个解析器资源耗尽问题,这次讲的这条是其中一个:页面树条目复制没有预算上限。

01  漏洞速览

漏洞编号CVE-2026-119204

影响产品pypdf < 6.21.4(Python 库)

漏洞类型资源耗尽型拒绝服务

危害等级7.1 高危(CVSS 4.0)

在野利用暂无公开记录

公开 PoC无独立 EXP,上游有复现用例

攻击前提服务端用 pypdf 解析攻击者可控 PDF

02  成因:被引用 N 次就复制 N 份

PDF 的页面树是一棵对象树,/Pages 节点用 /Kids 指向子节点,叶子是 /Page。规范允许同一个叶子页面被多个父节点同时引用,正常情况那只是一次引用,但 pypdf 展开页面树时是按引用逐份物化的:每遇到一次 /Page 引用,就新建一个 PageObject,把该页字典条目复制进去,再把父节点上未定义的继承属性补进去。

6.21.3 及之前的写法大致是这样:

每个引用都新建一页

page = PageObject(

self, item.indirect\_reference)

page.update(item.node)

for k, v in item.inherit.items():

if k not in page:

page[k] = v

问题在于全程没有任何预算控制:页面有几个键,复制一次就是几条;共享同一个叶子页的引用有多少个,就复制多少轮。构造一份只有几十 KB 的 PDF,让一个带 200 个键的叶子页被三层各 200 次引用,展开就是 200 × 200 × 200 等于八百万条字典条目,直接把内存吃干净。

6.21.4 的修法很直接:加一个全文档共享的条目预算,默认 200 万条,每复制一页先扣减,扣成负数就抛异常。

预算按引用计费

remaining.entry\_count -= count

if remaining.entry\_count < 0:

raise LimitReachedError(

\"Maximum page tree page \"

\"entry limit exceeded!\")

预算是按引用计费的:同一个页面被引用多次就复制多次、扣多次,这正好卡住放大倍数,而不是简单限制页数。配置项为 page\_tree\_maximum\_page\_entries。

03  影响范围

受影响 pypdf < 6.21.4,修复版本 6.21.4 及以上,升级就一条命令:

pip install -U pypdf

同一批次还有三个同族问题,都是解析器资源耗尽,评分同样是 7.1:

CVE-2026-119203:交叉引用表读到文件末尾却没有 trailer 时,trailer 搜索反复回卷到同一位置,线程卡死在死循环里,6.21.4 修复。

CVE-2026-119205:克隆循环引用的字典对象时,访问标记查的是生成后的目标引用而不是源引用,部分源侧环逃过检测,无限递归,6.21.4 修复。

CVE-2026-119206:page\_labels 逐页独立解析、每页都从头扫一遍标签数组,页数和标签区间一多,耗时按乘积增长,6.21.3 修复。也就是说,版本低于 6.21.4 的,这四个洞是一起暴露的。

04  利用分析:不用 EXP,卡解析入口

目前没有公开的独立利用工具,但危害路径不需要写代码也能推出来。攻击者投递一份构造过的 PDF,让它落在会用 pypdf 打开它的地方:文件上传接口、邮件附件自动提取、票据和简历识别、爬虫抓回来的文档、知识库导入。

服务端只要做了下面任意一件事,页面树就会展开:

· 取页数或遍历页面,比如 len(reader.pages)

· 抽取某一页文本 extract\_text()

· 合并、拆分、加密、加水印这类会走 append 的写入操作

一旦触发,内存占用跟文件体积几乎脱钩:文件几十 KB,展开后是几百万条字典。单请求就能把 worker 顶到内存上限被 OOM killer 干掉;换成并发,几十个请求就够让整个解析服务反复重启。

要提醒一点:从文件大小、页数、扩展名入手的前置校验拦不住它。页数计数可以随便伪造,真实的放大发生在解析之后的展开阶段。

05  检测与排查

先确认版本,低于 6.21.4 就要处理:

pip show pypdf | grep -i version

再定位业务里解析用户可控 PDF 的入口:

grep -rn \"PdfReader\|pypdf\" \

--include=\*.py app/ worker/

判断一份 PDF 有没有共享页面放大,数页面引用数跟去重后的数量差多少:

from pypdf import PdfReader

r = PdfReader(\"upload.pdf\")

ids = []

def walk(node):

for kid in node.get(\"/Kids\", []):

if kid.get(\"/Type\") == \"/Page\":

ref = kid.indirect\_reference

ids.append(ref.idnum)

else:

walk(kid)

root = r.trailer[\"/Root\"][\"/Pages\"]

walk(root)

print(len(ids), len(set(ids)))

引用总数远大于去重后的数量(十倍以上),基本就是刻意造的共享页面结构,直接拒收。线上再加一条监控:解析进程的常驻内存在单次请求内涨到平时数倍,先掐掉该任务再排查。

06  修复建议

  1. 升级到 pypdf 6.21.4 或更高,四个同族问题一次解决。

  2. 短期升不了级,就手工合入上游 PR #4290 的改动,把条目预算逻辑打进去。

  3. 兜底加固:解析放进独立子进程并设内存上限和超时;拒收重复引用同一页面对象、页数计数与实际不符的 PDF;上传接口按租户限速,别让并发打满解析队列。

子进程限额的最小写法:

import resource

limit = 1 << 30  # 1GB

resource.setrlimit(

resource.RLIMIT\_AS,

(limit, limit))

07  红队视角

这类洞不会给你 shell,但实战里很好用。入口太常见:文件上传、附件解析、文档导入几乎是每个业务系统都有的功能,还经常直接对着公网,比找一个未授权 RCE 容易得多。门槛也低:不需要绕认证,不需要交互,只要目标把文件交给 pypdf。

报告口径要写对。这类问题容易被当成低危 DoS 退回,落 CWE-400 资源无节制消耗或 CWE-770 无频率限制的资源分配更准确,再把放大倍数、单请求打挂的实测数据、打挂后解析链路不可用对业务的影响一起写进去,比一句可以造成拒绝服务有说服力得多。

防守侧反过来看也简单:把解析器一律当成不可信输入的边界,进程隔离加资源上限,比追着每一个 CVE 打补丁靠得住。

08  POC 链接

https://github.com/advisories/GHSA-cggf-277g-3q54

https://github.com/py-pdf/pypdf/security/advisories/GHSA-cggf-277g-3q54

https://github.com/py-pdf/pypdf/pull/4290

https://github.com/py-pdf/pypdf/commit/ea4ac663133f1b3de1d7a8f2e6fa239802fde79e

https://github.com/py-pdf/pypdf/releases/tag/6.21.4

说明:没有独立公开 EXP,上游测试用例 test\flatten\\_page\_tree\_maximum\_page\_entries 给出了完整构造方式与复现环境,可对着改造成检测样本。

下期继续蹲厂商补丁和 PoC 动静,关注后漏洞先知道,修复不踩坑。

— END —

一个政企安全项目的交付手记" 网络安全文章

一个政企安全项目的交付手记"

该文是政企安全项目交付复盘手记,作者总结四方面经验:需求治理需留痕并走流程避免范围蔓延;复杂干系人管理要明确权责、拉会踢球并向上管理;用高质量文档锁定交付成果,重视细节审核;拒绝情绪内耗,专注自身课题。核心在于将项目管理知识落地,通过流程化、文档化应对政企项目挑战。
pypdf一个PDF吃光内存,CVE-2026-119204" 网络安全文章

pypdf一个PDF吃光内存,CVE-2026-119204"

本文分析pypdf库CVE-2026-119204资源耗尽型拒绝服务漏洞,影响6.21.4以下版本。漏洞成因是页面树条目复制无预算上限,恶意PDF可致内存膨胀OOM。修复版本为6.21.4,建议升级或手工合入补丁,并采取子进程隔离、资源限额等加固措施。文章还提供检测脚本与红队利用视角。
150元破解6.4万元FSD:韩国80名特斯拉车主被移送检方" 网络安全文章

150元破解6.4万元FSD:韩国80名特斯拉车主被移送检方"

韩国80名特斯拉车主因非法激活FSD被移送检方,查扣21台破解设备。攻击利用CAN总线硬件中间人手法,伪造认证指令绕过区域限制,成本仅150元。事件暴露三大设计缺陷:授权判定缺少双向认证、全球硬件同构仅靠软件锁区分、车载日志由车主掌控。建议车企加强总线层双向认证与安全元件防护。
几分钟找出全部隐藏摄像头" 网络安全文章

几分钟找出全部隐藏摄像头"

本文介绍通过WiFi网络扫描定位隐藏摄像头的方法。核心思路是摄像头需联网传输视频,会留下MAC地址、IP、开放端口和流量模式等痕迹。操作步骤包括:用nmap扫描网段列出设备、让Claude分析MAC厂商识别可疑设备、检查554等摄像头常用端口、分析持续上传流量模式、结合户型图和信号强度定位。文章强调只扫描自有网络,发现摄像头后应拍照留证并报警。
评论:0   参与:  0