Hotdry.

Article

React Server Components 的 DoS 与源码泄露缺陷:服务端渲染流如何被恶意请求打满并暴露组件源码

聚焦 CVE-2025-55184/55183,给出可落地的流控、超时、监控参数,防止 RSC 端点被无限循环拖死或泄露 Server Function 源码。

2025-12-12ai-security

现象:CPU 100% 与源码裸露

12 月 11 日,React 官方追加披露两组 “非 RCE” 但同样影响生产的新漏洞:

  • CVE-2025-55184 & CVE-2025-67779(DoS,CVSS 7.5):攻击者发送一段 1 kB 左右的畸形 Flight payload,服务端反序列化时陷入无限循环,单核 CPU 瞬间 100%,进程失去响应。
  • CVE-2025-55183(源码泄露,CVSS 5.3):若 Server Function 的参数或返回值被隐式转换为字符串(如模板字面量拼接),React 会把整段函数源码序列化回客户端,硬编码的密钥、SQL 片段一览无余。

两洞均无需登录,且与上周的 RCE 洞共享同一入口 —— 任何可访问 /react-server-function(或框架自定义)端点的请求都能触发。这意味着在打完 RCE 补丁后,如果仅升级至 19.0.2 / 19.1.3 / 19.2.2,DoS 与泄露风险依然存在,必须继续升至 19.0.3 / 19.1.4 / 19.2.3 及以上。

原理:Flight 反序列化陷入死循环 & 函数 toString 回包

React Server Components 使用自研的 “Flight” 协议进行双向序列化。协议格式本身支持循环引用与 Promise 懒加载,实现时在服务端调用 parseModelString 递归展开引用。问题出现在两处:

  1. DoS 洞:攻击者可构造一个自引用的闭包对象 {"@":"$","f":"","b":"<self-ref>"},解析器在展开时不断压栈,最终触发无限递归。由于 Node.js 默认不限制调用栈深度,事件循环被彻底阻塞。
  2. 泄露洞:Server Function 在序列化返回值时,若检测到字段类型为 Function,会回退到 fn.toString(),把整段源码作为普通字符串塞进 JSON。只要开发者写了 message: \Hello, ${name}``,源码就会被原样带回到客户端。

影响面评估:谁会被打满 / 泄露

  • Next.js 15.x、16.x(App Router):默认暴露 /_next/server-function 端点,且框架自动开启 RSC,无需业务显式声明。
  • Waku、RedwoodJS、React Router RSC 预览版:同样依赖 react-server-dom-webpack,属于 “开箱即中毒”。
  • 纯 CSR 项目:未启用 RSC 则不受任何影响;一旦通过插件(如 @vitejs/plugin-rsc)打开服务端渲染,即落入射程。

根据 Censys 最新扫描,全球约 215 万个 IPv4 端口返回 X-Powered-By: Next.js,其中 68% 版本号落在 15–16 区间;即使按最保守 30% 开启 App Router 估算,也有 40 万台实例可被直接打满或拖库。

应急清单:版本号、WAF 规则、重启策略

动作 命令 / 配置
1. 立即升级 npm i next@15.0.6(或对应系列最新补丁)npm i react-server-dom-webpack@19.0.3
2. 快速自查 npm ls | grep "react-server-dom|next" | grep -E "19\.[0-2]\.[0-2]" 有输出即高危
3. 临时 WAF 阻断 Content-Type: text/x-componentPOST 请求体长度 >8 kB
4. 进程守护 PM2 配置 max_memory_restart: 500M,容器配置 livenessProbe 5 s 未响应即重启
5. 日志审计 出现 Unexpected thenableMaximum call stack 关键字即触发告警

注意:WAF 只能缓解批量扫描,无法拦截精心构造的小 payload,最终仍需靠版本升级。

长期参数:请求大小 ≤64 k、超时 ≤5 s、并发 ≤10

在框架层之上再加一层 “业务无关” 的硬限制,可显著降低同类漏洞的爆炸半径:

  1. 请求大小
    Nginx:client_max_body_size 64k;
    超过直接返回 413,避免大 payload 进入 Node 层。

  2. 超时
    Node:server.headersTimeout = 5000;
    单请求解析 + 执行上限 5 s,到点强制断开 socket,防止死循环拖死事件循环。

  3. 并发
    使用 p-limitasync-sema 把同一 RSC 端点的并发度压到 10,超出的请求立即 503,既保护 CPU,也保护内存。

  4. 监控
    Prometheus 样例:

    rsc_parse_duration_seconds{quantile="0.95"} > 4
    rsc_parse_errors_total{reason="InfiniteLoop"} increase(5m) > 0
    

    配合 Alertmanager 5 分钟内飞书 / Slack 告警。

  5. 灰度回滚
    金丝雀发布时,先对 1% 流量开启 RSC,观察 CPU 与 5xx 曲线 10 min 无异常再全量;一旦发现尖刺,一键回滚至 Pages Router 或纯静态版本。

小结

CVE-2025-55184/55183 再次证明:当 “前端” 框架越界到服务端,任何解析器缺陷都会直接转化为基础设施灾难。DoS 与源码泄露虽不如 RCE 惊悚,却更易被脚本小子大规模利用。升级补丁是底线,但生产环境仍需叠加 “小、快、短” 的流量策略 —— 请求体小、解析快、超时短 —— 才能把下一次未知漏洞的损害框在可控范围。

资料来源

ai-security