← 返回题目列表

XSS 攻击是什么?前端如何防范?

高频 中等 第 14 / 26 题 更新于 2026/07/28
前端安全XSS脚本注入

简化版

XSS 是攻击者把恶意脚本注入页面并在用户浏览器中执行。防范核心是不要让不可信内容变成可执行脚本,常见手段包括输出转义、富文本白名单过滤、避免危险 HTML、CSP、HttpOnly Cookie 和严格的输入校验。

详细版

XSS 常见类型:

  • 存储型:恶意内容存入数据库,用户访问时执行。
  • 反射型:恶意脚本通过 URL 参数反射到页面。
  • DOM 型:前端脚本把不可信数据写入 DOM 导致执行。

危害:

  • 窃取 token 或用户信息。
  • 伪造用户操作。
  • 篡改页面内容。
  • 发起恶意请求。

防护方式:

  • 模板插值默认转义。
  • 不随意使用 innerHTML
  • 富文本使用白名单过滤。
  • 设置 CSP 限制脚本来源。
  • Cookie 使用 HttpOnly 降低 token 被读风险。

完整版教学

一、XSS 的本质

XSS 的关键不是用户输入了危险字符,而是这些字符最终被浏览器当作脚本执行。

例如评论内容如果直接插入 HTML:

container.innerHTML = comment

攻击者提交 <script> 或带事件属性的标签,就可能执行恶意代码。

二、三类 XSS

存储型最危险,因为恶意内容会被保存,影响所有访问该内容的用户。

反射型通常依赖诱导用户点击恶意链接,服务端把参数原样输出到页面。

DOM 型发生在前端代码中,服务端可能完全没有参与。比如从 location.hash 读取内容后写入 innerHTML。

三、防护思路

最重要的是输出编码。普通文本应该按文本渲染,不要按 HTML 解释。

富文本不能简单转义所有标签,因为业务需要保留部分标签。这时要用白名单,只允许安全标签和安全属性。

CSP 是第二道防线。它可以限制脚本来源,禁止内联脚本,降低 XSS 成功后的破坏范围。

四、面试追问与工程落地

面试官可能问:“React/Vue 默认能防 XSS 吗?”

模板插值默认会转义文本,能防很多 XSS。但如果使用 dangerouslySetInnerHTMLv-html 或手动操作 innerHTML,仍然可能引入风险。

工程中安全不能只靠框架默认能力。富文本、Markdown、第三方脚本、用户生成内容都要重点审查。

五、输出上下文决定防护方式

同一个字符串放在不同位置,需要不同处理;不存在“统一替换尖括号就安全”的万能函数。

输出位置推荐方式典型危险点
HTML 文本使用 textContent/模板自动转义innerHTML
HTML 属性框架属性绑定并限制属性名事件属性、未加引号属性
URL解析协议并建立 allowlistjavascript:、危险 data URL
JavaScript 数据安全序列化,避免拼源码打断字符串或 script 标签
富文本成熟 sanitizer 白名单清洗标签、属性、URL 协议组合

比如评论有 10000 条,哪怕 9999 条正常,只要 1 条存储型 payload 被保存,就可能影响之后查看页面的所有用户。输入过滤可减少垃圾数据,但最终必须在每个输出 sink 按上下文处理。

心法:先把不可信数据当“数据”而不是 HTML;确需 HTML 时再进入经过审计的单一清洗通道。

六、DOM sink、CSP 与验证方法

危险 sink 不只 innerHTML,还包括 outerHTMLinsertAdjacentHTMLdocument.write、字符串形式的 setTimeout 等。代码审计应从这些 sink 反向追踪数据源,如 URL、postMessage、服务端响应、localStorage 和第三方 SDK。

// 安全展示普通文本
node.textContent = userComment

// 富文本必须先经过成熟且配置正确的 sanitizer
node.innerHTML = sanitize(userHtml)

CSP nonce/hash、Trusted Types、HttpOnly Cookie 都是纵深措施:CSP 限制执行来源,Trusted Types 收紧 DOM XSS sink,HttpOnly 减少 Cookie 被直接读走;它们都不修复原始注入点。

测试要覆盖存储型、反射型和 DOM 路径,并尝试标签、事件属性、危险 URL、SVG/MathML 等不同解析上下文。修复后既要证明 payload 不执行,也要回归合法富文本没有被破坏。

七、常见误区与追问

  • 误区:过滤 <script> 标签就能防 XSS。 事件属性、SVG、危险 URL 和大量解析上下文都可能执行代码。
  • 误区:只在输入时统一转义最安全。 数据未来输出上下文未知,过早编码会双重转义且仍可能用错编码。
  • 误区:React/Vue 项目不会出现 XSS。 普通插值较安全,但危险 HTML API、URL、第三方组件和手动 DOM 操作仍会引入漏洞。
  • 追问:存储型、反射型、DOM 型如何区分? 看恶意数据是否持久化、是否由响应反射、以及漏洞 sink 是否主要在客户端代码。
  • 追问:富文本为什么不能只做 HTML 转义? 业务需要保留部分标签,应按标签、属性和 URL 协议白名单清洗。
  • 追问:HttpOnly 能阻止 XSS 做什么? 它阻止脚本直接读取 Cookie,但不能阻止脚本代用户发请求。
  • 追问:CSP 为什么只是第二道防线? 配置可能有兼容放宽,且注入仍可能篡改页面或利用允许的能力。

八、加强记忆

  1. 本质:不可信数据进入可执行上下文,被浏览器解释成代码。
  2. 主防线:普通文本用安全 API,输出时按 HTML、属性、URL、JS 上下文编码。
  3. 富文本:集中使用成熟 sanitizer 的 allowlist,禁止自行拼过滤器。
  4. 审计方法:从危险 DOM sink 反查 URL、消息、存储和接口等数据源。
  5. 纵深措施:严格 CSP、Trusted Types、HttpOnly 降低漏网后的损失。
  6. 全面测试:覆盖存储、反射、DOM 三条路径及多种 HTML 解析上下文。