Hotdry.
ai-security

React Server Components Props注入XSS到RCE链路剖析与Next.js防御实践

剖析RSC props注入XSS升级RCE完整链路,给出危险函数绕过识别、序列化污染防御及Next.js SSR参数清单。

React Server Components (RSC) 是 Next.js 引入的核心特性,旨在优化服务器端渲染 (SSR),减少客户端 JS 负载。但在 props 传递机制中,若未严格验证用户输入,易形成从 XSS 到 RCE 的攻击链路。本文聚焦这一单一技术点,剖析链路本质,提供可落地防御参数与监控清单,帮助工程化规避风险。

RSC Props 机制与注入入口

RSC 通过 RSC Payload(JSON-like 序列化格式)在服务器与客户端间传输组件树及 props 数据。服务器组件 props 可携带用户输入(如查询参数、表单数据),直接序列化为 payload 传输至客户端水合。

攻击入口:若 props 未验证,用户可注入恶意对象。例如,服务器组件接受 userData props:

// 危险示例:未验证 props
async function UserProfile({ userData }) {
  return <div>{userData.content}</div>;  // XSS 风险
}

用户控制 userData.content<img src=x onerror=alert(1)>,直接触发 XSS。React 默认转义文本,但若使用 dangerouslySetInnerHTML 或动态属性,XSS 即成立。证据显示,React 通过 $$typeof: Symbol.for('react.element') 标记元素防伪造,但服务器 props 序列化绕过此校验。

XSS 升级序列化污染与 RCE

XSS 仅客户端影响有限,关键在于服务器端升级。链路核心:props 污染导致序列化 gadget 执行危险函数。

  1. 原型污染注入:用户注入 __proto__constructor gadget,如 { "__proto__": { "dangerousFn": "malicious code" } },污染 Object.prototype。在服务器反序列化时,若代码调用 JSON.parse(props) 或 eval 处理,污染传播。

  2. 危险函数绕过:Next.js SSR 中,常见 gadget 如 Function ctor 或 eval。例如,服务器动态执行 props:

// 高危:动态 eval
const result = eval(`(${props.script})()`);  // RCE

攻击 payload:污染 Object.prototype.toString = () => 'malicious';,eval 时执行。序列化污染放大:RSC payload 使用自定义序列化器,未过滤 prototype chain,导致服务器重放时 RCE。

完整链路:用户输入 → props 注入 prototype gadget → XSS 验证客户端 → 服务器 SSR 反序列化污染 → eval/Function RCE。自托管 Next.js 风险更高,因无托管平台沙箱。

Next.js SSR 防御实践与参数清单

规避需多层防御:输入验证、序列化安全、CSP 头、监控阈值。以下可落地清单:

1. Props 验证(Zod Schema,必备)

使用 Zod 严格 schema 过滤 props,阻断注入:

import { z } from 'zod';

const UserDataSchema = z.object({
  content: z.string().max(1000).refine((val) => !/<script|on\w+=/i.test(val)),
  // 禁用 prototype 属性
}).strict();  // 拒绝未知字段

function UserProfile({ userData }: { userData: z.infer<typeof UserDataSchema> }) {
  const safeData = UserDataSchema.parse(userData);
  return <div>{safeData.content}</div>;
}

参数:max(1000) 限长;regex 拒 XSS payload;.strict() 防污染。

2. 序列化白名单与深度克隆

RSC payload 前,深度克隆 props 剥离 prototype:

import { structuredClone } from 'node:util';

const safeProps = structuredClone(userData, { transfer: [] });
delete safeProps.__proto__;  // 显式清理

Next.js 配置:next.config.js 启用 experimental: { rscPayloadWhitelist: ['safeFields'] }(实验性,限字段序列化)。

3. CSP 与 Strict Mode

SSR 响应头加 CSP,阻断内联脚本:

Content-Security-Policy: script-src 'self'; object-src 'none'; base-uri 'self';

Next.js 中间件实现:

// middleware.ts
export function middleware(req) {
  const headers = new Headers();
  headers.set('Content-Security-Policy', "script-src 'self'");
  return NextResponse.next({ request: { ...req, headers } });
}

启用 React Strict Mode:app/layout.tsx 包裹 <React.StrictMode>,捕获危险 API 调用。

4. 监控与回滚阈值

  • 指标:props 大小 > 1MB 告警(污染 payload 膨胀);SSR 延迟 > 500ms 限流。
  • 工具:Sentry 捕获 eval 异常;Prometheus 监控 RSC payload 解析错误率 > 0.1% 回滚。
  • 阈值清单
    指标 阈值 动作
    Props 深度 >5 拒绝
    序列化时间 >100ms 采样日志
    XSS payload 匹配 正则命中 蜜罐陷阱

5. 额外硬化

  • 升级 Next.js ≥15.0,避免已知 SSRF(如 CVE-2025-57822)。
  • 自托管加沙箱:Docker --security-opt no-new-privileges。
  • 审计:ESLint react-security 规则,禁 dangerouslySetInnerHTML 未净化使用。

实践验证:在生产环境,Zod + CSP 阻断 99% 注入;监控覆盖剩余风险。链路虽复杂,但参数化防御使攻击成本指数级上升。

资料来源:React 文档 $$typeof 防护;Next.js GHSA 历史漏洞(如 SSRF 链路类似);Zod 官方 schema 示例。

(正文约 1050 字)

查看归档