Next.jsnext/og未授权RCE(CVE-2026-94545):一张图片换来服务器Shell"

admin 2026-10-15 16:27:53 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

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 被替换、进程计数异常
容器重启计数异常增长 每次命中都会触发一次非预期重启

---

Next.jsnext/og未授权RCE(CVE-2026-94545):一张图片换来服务器Shell" 网络安全文章

Next.jsnext/og未授权RCE(CVE-2026-94545):一张图片换来服务器Shell"

本文分析Next.jsnext/og组件CVE-2026-94545未授权RCE漏洞。漏洞源于Satori序列化SVG文本时未转义,攻击者可注入恶意SVG标记,在Noderuntime配合sharp时通过XInclude和DTD实体触发原生解析器内存破坏,最终实现远程代码执行。影响Next.js16.2.0-16.3.5及Satori0.0.27-0.33.4。建议升级至Next.js16.3.6或Satori0.33.5,并采取缓解措施。
评论:0   参与:  0