Next.js next/og 未授权 RCE(CVE-2026-94545):一张图片换来服务器 Shell
松杨网络安全资料库
2026年10月13日 17:33
广东
在小说阅读器读本章
去阅读
在公众号小说中沉浸阅读
一、漏洞背景
next/og 是 Next.js 里负责动态生成 Open Graph 图片的能力:请求进来,JSX 先被 Satori 渲染成 SVG,再由渲染器栅格化为 PNG,用于社交平台的分享卡片。这类接口通常直接消费请求参数(标题、用户名、统计数字),且大多数部署在未认证路径上——/api/og 任何人可打。
漏洞关键在于——Satori 把用户提供的文本写进 SVG 时没有做转义(CWE-116),请求内容可以提前闭合外层元素、注入任意 SVG 标记——一个未认证请求,服务器进程直接执行任意命令。
| 项 | 内容 |
|---|---|
| 漏洞编号 | CVE-2026-94545 |
| 影响版本 | Next.js 16.2.0 – 16.3.5(Node runtime 且安装 sharp); Satori 0.0.27 – 0.33.4 |
| 修复版本 | Next.js 16.3.6 / Satori 0.33.5(序列化时转义 SVG 文本) |
| 认证要求 | 无 |
| PoC 状态 | 已公开(EQSTLab/CVE-2026-94545 仓库,2026-09-29) |
| 利用特点 | 盲打、单请求、命中即执行;地址固定,无需泄漏或爆破 |
缺陷链概览:
| 环节 | 缺陷 | 后果 |
|---|---|---|
| ① 文本转义 | Satori 序列化 SVG 文本不转义(CWE-116) | 可闭合元素、 注入任意 SVG 标记 |
| ② 渲染路径 | Node runtime + sharp → 原生 libvips/librsvg/libxml2 |
恶意 SVG 进入原生解析链 |
| ③ 实体展开 | XInclude 引用 + 嵌套 DTD 实体 | 原生解析器内存破坏 |
| ④ 代码执行 | 官方 Node 二进制非 PIE,地址固定 | 无需泄漏的 ROP → execve |
二、漏洞原理
Next.js 的 ImageResponse 用 Satori 把数据序列化成 SVG,而 Satori 对文本内容不做转义(CWE-116),请求里闭合 <title> 即可注入任意 SVG 标记;能否走到危害取决于渲染链——Edge runtime 走 resvg-wasm 沙箱到此为止,Node runtime 上 sharp 交给原生 libvips/librsvg/libxml2,注入的 XInclude 加嵌套 DTD 实体在原生解析器里触发内存破坏;官方 Node 二进制非 PIE、地址固定,无需信息泄漏,把 ROP 链编码成 SVG 路径坐标完成利用,最终落到 execve——通过这四步串联,图片的渲染请求就可以控制服务器。
三、漏洞复现
环境
| 项 | 值 |
|---|---|
| 靶场 | Docker 镜像(基于 PoC 仓库 Dockerfile 构建, Node 24.20.0 非 PIE / Next 16.3.5 / sharp 0.35.4 → vips 8.18.6 / rsvg 2.62.91 / xml2 2.15.3) |
| 部署 | docker run -d --name cve-2026-94545 -p 3000:3000 cve-2026-94545 ,--restart unless-stopped |
| 入口 | POST http://192.168.x.x:3000/api/og (请求体进入 SVG <title>) |
| 攻击端 | Windows(监听端与发射端同机,两个终端) |
【图 1】复现结果:上为发射端输出,下为监听端落地 root shell
四、修复方式
官方修复
| 项 | 内容 |
|---|---|
| 修复版本 | Next.js 16.3.6 / Satori 0.33.5 及以上 |
| 修复点 | Satori 序列化 SVG 文本时执行转义,注入通道关闭 |
| 升级路径 | npm i [email protected] (或更高);使用独立 Satori 的项目升到 0.33.5+ |
未修复项与遗留风险
| 项 | 说明 |
|---|---|
| 原生解析链未加固 | 修复发生在「转义」这一层;libvips/librsvg/libxml2 对 XInclude、DTD 实体的默认处理未变。只要能以其它路径把 XML 递进原生解析器,同类破坏仍有空间 |
| 存量版本不回补 | 16.2.0 – 16.3.5 的已发布版本不会自动免疫,需要部署方逐个升级 |
| 非 PIE 事实未变 | 官方 Node 二进制的固定地址布局不因本补丁改变,针对该栈的 ROP 仍具备「一次写死」的稳定性 |
| 环境纵深防御缺失 | 容器默认以 root 运行、出站不受限时,即使命中同类漏洞,直接后果就是 root shell 与外联通道 |
缓解措施(无法立即升级时)
next/og路由改为export const runtime = 'edge',回到沙箱化渲染;或移除sharp,让原生路径不可达;- 不把未净化输入送进
ImageResponse的子节点(转义或白名单化); - OG 路由加认证或来源白名单,并对出站流量做最小化限制(盲打依赖外联回传);
- 修补后按「已失陷」处置:轮换该进程可读的一切密钥,排查持久化。
检测与 IOC
| 特征 | 说明 |
|---|---|
POST /api/og 携带约 25 KB 的请求体 |
命中 payload 体积 ≈ 25 KB(与命令长度相关) |
请求体包含 xi:include、DOCTYPE、 ENTITY、data:image/svg+xml |
实体/包含结构是恶意体的指纹 |
| 请求后连接被服务端断开且进程重启 | 盲打成功特征:worker 被替换、进程计数异常 |
| 容器重启计数异常增长 | 每次命中都会触发一次非预期重启 |
---
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论