React Flight 协议安全:React2Shell 漏洞与 RSC 反序列化攻击深度分析
Smashing Magazine 发表深度技术文章,由 Durgesh Pawar 撰写,详细分析了 React Server Components(RSC)所使用的 Flight 协议中的安全漏洞。文章拆解了 CVSS 评分 10.0 的"React2Shell"漏洞的技术原理,展示了协议操纵如何导致远程代码执行(RCE)。同时提供了一套按优先级排序的防御措施,从严格的 schema 验证到 CSRF 加固,帮助开发者保护 React 应用免受这些结构性风险的影响。
背景:React Server Components 与 Flight 协议
RSC 的工作方式
React Server Components(RSC)不向浏览器发送 HTML,也不发送 JSON。当服务器组件渲染时,通过网络传输的实际上是一种名为 Flight 的自定义流式协议。
Flight 协议的特点:
- 行分隔格式(line-delimited format)
- 自定义类型系统
- 引用解析机制
- 在客户端重建可执行行为的规则
大多数开发者不了解 Flight
大多数 React 开发者从未打开 Network 标签页真正查看过 Flight 负载。它看起来像是 JSON 片段、美元符号前缀的引用和模块指针的混合体,React 运行时在客户端静默地将其重新组装为活动的组件树。
框架处理了这一切,所以很少有人质疑它。但这种信任实际上意味着:
- 客户端盲目信任服务器发送的 Flight 数据
- Flight 数据中可能包含可执行的引用
- 反序列化过程中可能触发危险操作
- 攻击者如果能操纵 Flight 数据,可能获得远程代码执行能力
React2Shell:CVSS 10.0 的严重漏洞
漏洞概述
React2Shell 是一个影响 React Server Components 的严重漏洞,CVSS 评分为 10.0(最高严重级别)。该漏洞允许攻击者通过操纵 Flight 协议数据,在服务器或客户端上执行任意代码。
攻击原理
攻击的核心在于 Flight 协议的反序列化机制:
- Flight 负载包含引用:Flight 协议使用
$符号前缀的引用来指向模块、函数或其他可执行实体 - 客户端反序列化:React 运行时在客户端解析 Flight 负载,解析引用并重建组件树
- 引用解析:引用被解析为实际的模块或函数
- 代码执行:如果攻击者能够操纵引用指向恶意模块或函数,反序列化过程中就可能执行任意代码
攻击场景
典型的攻击场景包括:
- 中间人攻击(MITM):攻击者在网络层截获并修改 Flight 响应
- CDN 缓存投毒:攻击者通过缓存投毒,让受害者收到被篡改的 Flight 数据
- 服务端请求伪造(SSRF):攻击者利用 SSRF 漏洞控制 RSC 的数据源
- 跨站请求伪造(CSRF):攻击者诱导受害者的浏览器发送恶意请求,触发不安全的 RSC 渲染
- 供应链攻击:攻击者污染依赖包,在 Flight 序列化过程中注入恶意引用
Flight 协议的反序列化风险
1. 模块引用注入
Flight 协议允许引用服务器端模块。如果攻击者能够注入恶意模块引用:
- 客户端可能加载并执行恶意模块
- 恶意模块可能包含后门或窃取数据的代码
- 模块路径验证不严格时,攻击者可以指向任意文件
2. 函数引用劫持
Flight 协议支持引用函数作为 props 或回调。攻击者可以:
- 将合法函数引用替换为恶意函数
- 在组件渲染时触发恶意函数执行
- 通过函数调用链实现权限提升
3. 原型污染
Flight 反序列化过程中,如果对象的 __proto__ 或 constructor.prototype 被操纵:
- 可能污染全局对象原型
- 影响所有后续对象的行为
- 可能导致权限绕过或代码执行
4. 类型混淆
Flight 协议有自己的类型系统。如果攻击者能够混淆类型:
- 字符串可能被当作函数引用解析
- 数字可能被当作模块 ID 解析
- 普通对象可能被当作可执行实体处理
- 类型混淆可能导致意外的代码执行
5. 循环引用和拒绝服务
Flight 协议支持引用解析。攻击者可以构造:
- 循环引用导致无限递归
- 深度嵌套导致栈溢出
- 大量引用导致内存耗尽
- 这些可能导致拒绝服务(DoS)攻击
防御措施(按优先级排序)
1. 严格的 Schema 验证(最高优先级)
对所有传入的 Flight 数据进行严格的 schema 验证:
- 定义允许的模块引用白名单
- 验证函数引用的签名和来源
- 限制对象的嵌套深度和大小
- 检查类型标签的合法性
- 拒绝任何不符合 schema 的数据
实现建议:
- 在服务器端序列化前验证数据
- 在客户端反序列化前验证数据
- 使用专门的 Flight 验证库
- 定期审计 schema 定义
2. CSRF 加固
RSC 端点容易受到 CSRF 攻击,因为它们通常基于 GET 请求:
- 为 RSC 端点实现 CSRF token 验证
- 使用 SameSite cookie 属性
- 验证 Origin 和 Referer 头
- 对敏感操作使用 POST 而非 GET
- 实现自定义的请求签名机制
3. 传输层安全
确保 Flight 数据在传输过程中不被篡改:
- 强制使用 HTTPS/TLS
- 实现 HSTS(HTTP Strict Transport Security)
- 使用证书固定(Certificate Pinning)在移动应用中
- 监控异常的 TLS 握手
- 考虑对 Flight 负载进行端到端签名
4. CDN 缓存安全
如果使用 CDN 缓存 RSC 响应:
- 严格配置缓存键,包含所有影响响应的请求头
- 禁用对包含用户特定数据的响应的缓存
- 实现缓存中毒检测和防护
- 定期审查 CDN 配置
- 使用 CDN 的 WAF 功能过滤恶意请求
5. 最小权限原则
限制 RSC 渲染过程中的权限:
- 服务器组件在沙箱环境中运行
- 限制文件系统访问
- 限制网络访问(只允许必要的 API 调用)
- 使用最小权限的数据库账户
- 避免在服务器组件中执行动态代码(eval、new Function 等)
6. 输入验证和输出编码
对所有用户输入进行严格验证:
- 验证 URL 参数、查询字符串和请求体
- 对输出到 Flight 负载的数据进行编码
- 避免将用户输入直接用作模块引用或函数名
- 使用参数化查询,避免注入攻击
- 实现输入长度和格式限制
7. 依赖管理
保护供应链安全:
- 定期更新 React 和相关依赖
- 使用 lockfile 确保依赖版本一致性
- 扫描依赖中的已知漏洞
- 使用 npm audit 或类似工具
- 考虑使用私有 npm 注册表,控制包来源
8. 监控和告警
建立安全监控机制:
- 监控异常的 Flight 负载(大小、结构、引用模式)
- 告警可疑的模块引用或函数调用
- 记录所有 RSC 请求和响应
- 实现速率限制,防止暴力攻击
- 定期进行安全审计和渗透测试
实战建议
对于使用 Next.js App Router 的团队
Next.js App Router 大量使用 RSC 和 Flight 协议。建议:
- 保持 Next.js 版本最新,及时应用安全补丁
- 审查
next.config.js中的安全配置 - 使用 Next.js 的内置安全头(security headers)
- 对动态路由参数进行严格验证
- 避免在服务器组件中使用
eval或动态import
对于自建 RSC 框架的团队
如果团队自建了 RSC 实现:
- 仔细审查 Flight 序列化和反序列化代码
- 实现模块引用白名单
- 添加严格的类型检查
- 进行模糊测试(fuzz testing)
- 考虑使用 React 官方的 Flight 实现而非自建
对于安全团队
- 将 RSC/Flight 协议纳入安全评估范围
- 开发专门的 Flight 协议安全测试工具
- 培训开发者了解 Flight 协议的安全风险
- 建立 RSC 安全最佳实践指南
- 关注 React 安全公告和 CVE
总结
React Server Components 的 Flight 协议为 RSC 提供了高效的流式传输机制,但也引入了严重的反序列化安全风险。React2Shell 漏洞(CVSS 10.0)展示了协议操纵如何导致远程代码执行,模块引用注入、函数引用劫持、原型污染、类型混淆和循环引用等都是潜在的攻击向量。保护 React 应用需要采取多层防御措施,按优先级包括:严格的 schema 验证、CSRF 加固、传输层安全、CDN 缓存安全、最小权限原则、输入验证和输出编码、依赖管理以及监控和告警。对于使用 Next.js App Router 或自建 RSC 框架的团队来说,理解 Flight 协议的安全风险并实施相应的防御措施至关重要。随着 RSC 在 React 生态中的普及,Flight 协议的安全将成为前端安全的重要领域。开发者不应该因为"框架会处理"就忽视底层协议的安全——理解信任边界并实施纵深防御是构建安全 React 应用的关键。
来源:https://smashingmagazine.com/2026/07/weaponizing-defending-react-flight-protocol/