CVE-2025-55182 · React2Shell:通过原型污染在 React Server Components 中实现 RCE

发布: (2026年5月3日 GMT+8 15:12)
5 分钟阅读
原文: Dev.to

Source: Dev.to

TL;DR

React 的 Flight 反序列化器将任何具有 .then 方法的对象视为 Promise。通过使用精心构造的 multipart POST 污染 Object.prototype.then,攻击者可以迫使服务器通过 Function 构造函数执行任意 JavaScript。结果通过 X-Action-Redirect HTTP 头部泄露。无需身份验证。确定性。CVSS v3.1:10.0(关键)

背景

React Server Components(RSC)在 React 19 中与 Server Actions 一起正式稳定。UI 组件在服务器上执行,并通过 Flight 序列化协议与客户端通信。当客户端调用 Server Action 时,会发送一个包含序列化负载的 multipart POST。服务器对负载进行反序列化,执行该动作,并将结果流式返回。

Flight 协议 不是 JSON;它是一种带有类型块的流式格式。其核心机制会将任何拥有 .then 函数的反序列化对象解析为 Promise。这个假设是漏洞的根源。

受影响范围: 使用 App Router 并启用 React Server Components 的任何 Next.js 应用(自 Next.js 14 起默认启用)。不需要显式定义 Server Actions;只要存在受漏洞影响的 RSC 包即可。

易受攻击的代码(React 19.0.0 – 19.2.0)

// VULNERABLE
if (obj && typeof obj.then === 'function') {
  // behavioral check — bypassable via prototype chain
}

如果攻击者在 Object.prototype 上添加 then 函数,所有普通对象都会继承它。反序列化器无法再区分真正的 Promise 与被污染的对象,最终会执行:

new Function(_prefix)   // attacker‑controlled code

利用步骤

侦察

识别运行 React 19.0.0–19.2.0 且使用 App Router 的 Next.js 应用。任何处理 multipart/form-data 并期望 Next-Action 头的端点都是有效目标。无需事先了解应用的路由。

负载构造

创建一个 multipart 请求体,使其:

  1. __proto__:then 设置为污染 Object.prototype
  2. _formData.get 重定向到 $1:constructor:constructor
  3. _prefix 中提供要执行的 JavaScript 代码。

请求发送

向根路径发送单个 POST 请求,携带头部 Next-Action: x。请求看起来是一个格式正确的 multipart 负载,因此大多数 WAF 会在不检查的情况下转发它。

服务端评估

在反序列化过程中,Flight 运行时遇到一个 .then 方法来源于已被污染的原型的对象,并调用 new Function(_prefix),从而执行攻击者的代码。

数据外泄

execSync() 的输出被插入到 NEXT_REDIRECT 错误摘要中。Next.js 将其转换为 307 响应,并在响应头中加入:

X-Action-Redirect: /login?a=

a 参数进行解码即可得到命令输出。

基本 RCE 示例

通过单个 POST 请求即可在受漏洞影响的 Node.js 服务器上执行诸如 whoamiiduname -a 等命令。

完整利用资源

完整的负载结构、最小的 curl 单行命令以及利用框架 react2shell.py(包括持久交互式 shell、环境变量泄漏、网页篡改和选择性拒绝服务模块)已在 blog.deviannt.com 文档中记录。

补丁详情

代码更改

// VULNERABLE
- resolvedValue = resolvedValue[key];

// PATCHED
+ if (!resolvedValue.hasOwnProperty(key)) break;
+ resolvedValue = resolvedValue[key];

hasOwnProperty 检查阻止了原型链遍历,防止攻击者通过 $1:constructor:constructor 访问 Function 构造函数。

验证你的安装

node -e "const r = require('react'); const [maj,min,pat] = r.version.split('.').map(Number); \
  console.log('React:', r.version, (maj===19 && (min<2||(min===2&&pat<1))) ? '❌ VULNERABLE' : '✓ Patched')"

补丁后建议

最初的补丁版本(19.0.119.1.219.2.1)仍包含两个后续 CVE:

  • CVE‑2025‑55184 – 拒绝服务(CVSS 7.5)
  • CVE‑2025‑55183 – 源代码泄露(CVSS 5.3)

请升级到 19.0.219.1.319.2.2 以获得完整修复。

结论

该漏洞源于依赖行为检查(typeof obj.then === 'function')而非身份检查。这种为支持“thenable”而设计的灵活性,在出现原型污染时就成了万能钥匙。必须进行恰当的原型链防护并采用更严格的类型验证,才能防止类似问题。

Full analysis → blog.deviannt.com · CVE‑2025‑55182 · React2Shell
— devianntsec, security research & beyond

0 浏览
Back to Blog

相关文章

阅读更多 »

Claude 运行快速。Codex 发布。

摘要:我给 Claude 和 Codex 两个大型编码任务。- Claude 大约在一小时内完成。- Codex 大约用了八小时。乍一看,这看起来像是……