React 项目中的 XSS 风险点与防御策略

=====================================

XSS(跨站脚本攻击)长期占据 OWASP Top 10 的显眼位置。React 作为当前主流前端框架,凭借 JSX 的默认转义机制,在一定程度上降低了 XSS 的发生概率。但“降低”不等于“消除”。在实际项目中,开发者一旦绕过 React 的安全设计,或者在后端、第三方库、服务端渲染等环节出现疏漏,XSS 依然可以轻易得手。本文从 React 项目的实际场景出发,梳理常见风险点,并给出可落地的防御策略。

React 为什么不能完全避免 XSS

React 在渲染文本内容时,会将变量中的特殊字符进行转义。例如 {userInput} 写入 JSX,<script> 会被转义为 &lt;script&gt;,浏览器不会将其当作标签执行。这是 React 内置的第一道防线。

但问题在于,React 提供了多个“逃生舱口”,允许开发者直接操作 HTML。一旦使用不当,转义机制就形同虚设。此外,XSS 并不只发生在前端渲染阶段,后端接口返回的数据、URL 参数、服务端渲染的 HTML 拼接,都可能成为攻击入口。

React 项目中常见的 XSS 风险点

1. dangerouslySetInnerHTML

这是 React 中最典型的 XSS 入口。当需要渲染富文本、Markdown 转换后的 HTML 时,开发者往往会使用 dangerouslySetInnerHTML。如果传入的 HTML 字符串未经净化,攻击者可以注入 <img src=x onerror=alert(1)><script> 标签,直接执行任意脚本。

// 危险写法:直接渲染用户提交的 HTML
<div dangerouslySetInnerHTML={{ __html: userContent }} />

2. href 与 src 中的 javascript: 协议

React 不会对 hrefsrc 属性的值做协议白名单校验。如果攻击者能够控制链接地址,可以构造 javascript:alert(document.cookie),用户点击后即触发脚本。

// 危险写法:用户可控的链接地址
<a href={userProvidedUrl}>点击查看</a>

3. 服务端渲染(SSR)中的字符串拼接

在 Next.js、Remix 等 SSR 框架中,如果开发者手动拼接 HTML 字符串返回给客户端,React 的转义机制不会介入。任何未经过滤的用户输入拼入模板,都会造成反射型或存储型 XSS。

4. 第三方组件与 Markdown 渲染

富文本编辑器、Markdown 渲染库、代码高亮组件等第三方依赖,如果配置不当或版本存在漏洞,也可能引入 XSS。例如某些 Markdown 解析器默认允许内联 HTML,攻击者可以通过 Markdown 注入脚本。

5. URL 参数与路由状态

location.searchlocation.hash 或路由参数中读取的数据,如果直接渲染到页面上,同样可能携带恶意脚本。这类风险在单页应用中尤为常见。

前端防御策略

1. 对富文本进行严格净化

如果必须使用 dangerouslySetInnerHTML,务必在渲染前使用 DOMPurify 等专业库对 HTML 进行净化。DOMPurify 会移除所有危险标签和属性,只保留安全的 HTML 子集。

import DOMPurify from 'dompurify';

const cleanHtml = DOMPurify.sanitize(userContent);
<div dangerouslySetInnerHTML={{ __html: cleanHtml }} />

同时,配置 DOMPurify 时明确允许的标签和属性白名单,避免过度放行。

2. 校验 URL 协议

对于用户可控的链接,渲染前检查协议是否为 http:https:mailto: 等安全协议。可以使用 new URL() 解析后判断 protocol 字段,拒绝 javascript:data: 等危险协议。

function safeUrl(url) {
  try {
    const parsed = new URL(url, window.location.origin);
    if (['http:', 'https:', 'mailto:'].includes(parsed.protocol)) {
      return parsed.href;
    }
  } catch (e) {}
  return '#';
}

3. 避免直接拼接 HTML

在 SSR 场景中,优先使用框架提供的模板引擎和转义机制,不要手动拼接 HTML 字符串。如果必须拼接,对每个变量使用 HTML 实体编码。

4. 设置 Content Security Policy(CSP)

CSP 是纵深防御的重要手段。通过 HTTP 响应头限制脚本来源,即使攻击者成功注入脚本,浏览器也会拒绝执行。推荐配置:

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

在 React 项目中,避免使用 unsafe-inlineunsafe-eval。如果使用了 styled-components 等运行时样式库,可以通过 nonce 或 hash 方式兼容。

5. 谨慎选择第三方依赖

定期审计项目依赖,关注安全公告。对于 Markdown 渲染、富文本展示类库,确认其默认配置是否安全,必要时关闭内联 HTML 解析功能。

6. 对 Cookie 设置 HttpOnly

虽然这属于后端措施,但对前端防御 XSS 同样关键。将敏感 Cookie 标记为 HttpOnly,即使 XSS 成功执行,攻击者也无法通过 document.cookie 窃取会话凭证。

总结

React 的默认转义机制是一道有效但并非万能的防线。真正的安全需要开发者在每个数据流入点保持警惕:净化富文本、校验 URL、避免手动拼接 HTML、配置 CSP、审慎使用第三方库。XSS 防御不是一次性的工作,而是贯穿开发、测试、部署全流程的持续实践。只有将前端防御与后端过滤、CSP 策略、Cookie 安全属性结合起来,才能构建起真正可靠的纵深防御体系。

未经允许不得转载:任鹏个人博客 » React 项目中的 XSS 风险点与防御策略

赞 (0) 打赏

评论 0

取消
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏