XSS 攻击是什么?

一、XSS 攻击是什么?

XSS(Cross-Site Scripting,跨站脚本攻击)是一种常见的 Web 安全漏洞,攻击者通过在网页中注入恶意脚本(JavaScript、HTML、CSS 等),当用户访问被注入的页面时,恶意脚本会在用户的浏览器中执行,从而实现窃取用户信息(Cookie、Token)、伪造用户操作、劫持会话、植入恶意广告等恶意行为。

XSS 攻击的核心本质:

违背 “前端渲染数据不可执行” 的原则—— 正常情况下,前端展示的用户输入 / 第三方数据应作为 “纯文本” 处理,若被当作 “可执行代码” 解析,就会触发 XSS。

XSS 的分类(按触发方式):

类型 触发场景 示例
存储型 XSS 恶意脚本被永久存储在服务器(数据库 / 文件),用户访问页面时从服务器加载执行 攻击者在论坛发帖时注入 <script>偷Cookie()</script>,所有查看该帖的用户都会执行脚本
反射型 XSS 恶意脚本通过 URL 传入,服务器 “反射” 回页面中执行(一次性,不存储) 攻击者构造链接 http://xxx.com/search?key=<script>恶意代码</script>,用户点击后执行
DOM 型 XSS 恶意脚本通过前端 DOM 操作直接执行(无需服务器参与) 前端通过 document.write(location.hash) 将 URL Hash 内容写入页面,若 Hash 含恶意脚本则执行

二、XSS 攻击的危害

  1. 窃取敏感信息:获取用户 Cookie、LocalStorage、Token,冒充用户身份登录系统;
  2. 劫持用户会话:利用窃取的信息操作用户账户(转账、发帖、修改密码);
  3. 植入恶意内容:弹出广告、跳转钓鱼网站、挖矿脚本;
  4. 破坏页面结构:篡改网页内容,诱导用户操作(如虚假登录框)。

三、XSS 攻击的防范方案(核心:输入过滤 + 输出转义 + 安全策略)

1. 核心原则:永远不信任用户输入

所有来自用户、第三方接口、URL 参数的数据,都必须视为 “不可信”,需经过处理后再使用。

2. 输出转义(最基础、最关键)

将渲染到页面中的特殊字符(如 < > & " ')转义为 HTML 实体,让浏览器将其视为纯文本而非可执行代码。

特殊字符 转义后的 HTML 实体 作用
< < 禁止解析为标签开始
> > 禁止解析为标签结束
" " 禁止解析为属性引号
' ' 禁止解析为单引号
& & 禁止解析为实体开始
实战实现:
  • 原生 JS

    :使用

    1
    textContent

    (而非

    1
    innerHTML

    )渲染文本(自动转义);

    1
    2
    3
    4
    // 安全:textContent 会将内容作为纯文本
    document.getElementById("content").textContent = userInput;
    // 危险:innerHTML 会解析 HTML/脚本
    document.getElementById("content").innerHTML = userInput;
  • 框架自动转义

    :Vue/React 等现代框架默认对插值表达式(

    1
    {{ }}

    /JSX)进行转义,无需手动处理;

    1
    2
    3
    4
    <!-- Vue 安全:自动转义 -->
    <div>{{ userInput }}</div>
    <!-- Vue 危险:v-html 会解析 HTML,需谨慎使用 -->
    <div v-html="userInput"></div>
  • 手动转义函数

    (针对必须用

    1
    innerHTML

    的场景):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function escapeHtml(str) {
    if (!str) return "";
    return str
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#39;");
    }
    // 使用
    document.getElementById("content").innerHTML = escapeHtml(userInput);

3. 输入过滤(补充手段)

对用户输入的内容进行 “白名单过滤”—— 只允许合法的字符 / 标签 / 属性,过滤掉恶意内容(如 <script>onclick 等)。

适用场景:

用户需要输入富文本(如编辑器、评论)时,无法完全转义(需保留部分 HTML 标签),此时需过滤危险标签 / 属性。

实战工具:
  • 专业富文本过滤库:

    1
    DOMPurify

    (主流推荐,能安全过滤恶意代码,保留合法 HTML);

    1
    2
    3
    4
    import DOMPurify from 'dompurify';
    // 过滤后再渲染富文本
    const safeHtml = DOMPurify.sanitize(userInput);
    document.getElementById("editor").innerHTML = safeHtml;
  • 后端过滤:如 Java 的 Jsoup、PHP 的 HTMLPurifier,对提交的内容进行服务端过滤。

4. 安全策略:CSP(内容安全策略)

CSP 是浏览器的安全机制,通过 HTTP 响应头或 meta 标签限制页面可加载的资源、可执行的脚本来源,从根源上阻止恶意脚本执行(即使漏过了转义 / 过滤)。

核心作用:
  • 禁止内联脚本(<script>...</script>onclick 等);
  • 禁止未授权的外部脚本(只允许加载指定域名的脚本);
  • 禁止 eval()new Function() 等动态执行代码的方式。
实战配置:
  • HTTP 响应头

    (推荐,由服务端设置):

    1
    Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.jsdelivr.net; style-src 'self'; img-src 'self' data:;

    解释:

    • default-src 'self':默认只允许加载同域名资源;
    • script-src 'self' https://cdn.jsdelivr.net:只允许执行同域名和 jsdelivr 的脚本;
    • 禁止内联脚本、eval 等。
  • meta 标签

    (前端配置,优先级低于响应头):

    1
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">

5. 其他辅助防范手段

(1)Cookie 保护:HttpOnly + Secure
  • HttpOnly:设置该属性的 Cookie 无法被 JavaScript 读取(直接阻断窃取 Cookie 的 XSS 攻击);

  • Secure:Cookie 仅在 HTTPS 协议下传输,防止明文传输被劫持;

  • SameSite
    
    1
    2
    3
    4
    5
    6

    :限制 Cookie 跨站发送,防止 CSRF 同时辅助防范 XSS。

    ```http
    // 服务端设置 Cookie 响应头
    Set-Cookie: sessionId=xxx; HttpOnly; Secure; SameSite=Strict;
(2)避免使用危险的 API

禁用 / 谨慎使用可执行动态代码的 API,减少 XSS 触发点:

  • 危险 API:eval()new Function()innerHTMLdocument.write()location.hash 直接渲染;
  • 安全替代:textContentsetAttribute(设置属性)、DOMPurify 过滤后再用 innerHTML
(3)服务端验证 + 前端验证双保险
  • 前端:做基础的输入格式验证(如手机号、邮箱格式),提升用户体验;
  • 服务端:必须重新验证所有输入(前端验证可被绕过),过滤恶意内容。
(4)URL 参数处理

对 URL 中的 queryhash 等参数,转义后再渲染到页面,避免反射型 / DOM 型 XSS:

1
2
3
4
5
6
7
// 危险:直接将 hash 写入页面
const hash = location.hash.slice(1);
document.body.innerHTML = hash;

// 安全:转义后再处理
const safeHash = escapeHtml(location.hash.slice(1));
document.body.textContent = safeHash;

四、XSS 防范总结(优先级排序)

  1. 输出转义:所有非富文本内容用 textContent/ 框架插值渲染,富文本用 DOMPurify 过滤;
  2. CSP 策略:配置严格的内容安全策略,兜底阻止恶意脚本执行;
  3. Cookie 保护:设置 HttpOnly/Secure,防止敏感 Cookie 被窃取;
  4. 输入过滤:服务端 + 前端双端过滤危险内容;
  5. 禁用危险 API:减少不必要的动态代码执行。

五、常见误区

  1. “前端转义就够了”:前端转义可被绕过(如攻击者直接请求接口),必须在服务端再次转义 / 过滤;
  2. “富文本无法防范 XSS”:使用 DOMPurify 等专业库可安全处理富文本;
  3. “HTTPS 能防 XSS”:HTTPS 仅保证传输安全,无法阻止页面内的恶意脚本执行;
  4. “框架完全安全”:Vue/React 的 v-html/dangerouslySetInnerHTML 仍可能触发 XSS,需谨慎使用。

XSS 攻击的核心是 “脚本注入”,防范的核心是 “让恶意脚本无法执行”—— 通过转义让脚本变成文本,通过 CSP 限制脚本来源,通过 HttpOnly 保护敏感数据,多维度防护才能彻底规避风险。