什么是 XSS 攻击 (跨站脚本攻击)?如何防御?
XSS 攻击(Cross-Site Scripting,跨站脚本攻击)是 Web 安全中最常见的一种漏洞。为了避免与 CSS(层叠样式表)混淆,缩写为 XSS。
简单来说,XSS 攻击是指攻击者在 Web 页面中植入恶意的脚本代码(通常是 JavaScript),当用户浏览该页面时,嵌入的脚本代码会被执行,从而达到恶意目的。
一、 XSS 攻击的原理与危害
1. 原理
Web 浏览器通常会将服务器返回的内容当作 HTML/JavaScript 解析并执行。如果服务器没有对用户的输入进行严格的过滤或转义,直接将其拼接到 HTML 中返回给浏览器,浏览器就会把用户的输入当作代码执行。
例子:
假设一个搜索页面,会在页面上显示:“你搜索的内容是:[用户输入]”。
如果用户输入 hello,页面显示 你搜索的内容是:hello。
如果用户输入 <script>alert('hack')</script>,页面源码变成:你搜索的内容是:<script>alert('hack')</script>
浏览器看到 <script> 标签,就会执行里面的代码,弹出一个对话框。
2. 危害
一旦脚本在受害者的浏览器中执行,攻击者可以:
- 窃取 Cookie/Session: 获取用户的登录凭证,从而盗取账号。
- 监听用户行为: 记录键盘输入(如银行卡号、密码)。
- 修改页面内容: 伪造登录框(钓鱼),诱导用户输入密码。
- 强制重定向: 将用户跳转到恶意网站。
- 蠕虫传播: 在社交网站上自动关注、点赞或转发恶意链接。
二、 XSS 攻击的三种类型
根据攻击代码的来源和持久性,XSS 分为三类:
1. 反射型 XSS (Reflected XSS)
- 特点: 非持久化。恶意代码在 URL 参数中,服务器接收参数后直接反射回页面。
- 场景: 搜索框、错误提示页面。
- 攻击流程:
- 攻击者构造一个带有恶意参数的 URL(例如:
http://site.com/search?q=<script>...)。 - 诱导用户点击该链接(通常通过邮件、社交软件)。
- 服务器将 URL 中的脚本反射回 HTML,浏览器执行脚本。
- 攻击者构造一个带有恶意参数的 URL(例如:
2. 存储型 XSS (Stored XSS) —— 危害最大
- 特点: 持久化。恶意代码被保存到了服务器的数据库中。
- 场景: 论坛发帖、商品评论、用户留言、修改个人简介。
- 攻击流程:
- 攻击者在评论区提交包含恶意脚本的内容。
- 服务器将该内容存入数据库。
- 任何访问该评论页面的用户,都会从数据库加载并执行该恶意脚本。
3. DOM 型 XSS (DOM-based XSS)
- 特点: 不需要服务器参与,纯粹是客户端 JavaScript 逻辑问题。
- 场景: 前端 JS 代码直接从 URL 或输入框取值,并动态修改 DOM(如使用
innerHTML、document.write)。 - 攻击流程:
- 前端代码逻辑如:
document.getElementById('div').innerHTML = location.hash; - 攻击者构造 URL:
http://site.com#<img src=x onerror=alert(1)> - 浏览器执行 JS,将恶意代码插入页面并执行。
- 前端代码逻辑如:
三、 如何防御 XSS 攻击?
防御 XSS 的核心原则是:永远不要信任用户的输入,将“数据”与“代码”分离。
1. 输入过滤 (Input Validation)
在数据进入系统之前进行检查。
- 黑名单/白名单: 过滤掉
<script>,javascript:,onclick等敏感字符。 - 限制格式: 比如年龄只能是数字,URL 必须以 http 开头。
- 注意:仅靠输入过滤很难完全防御,因为攻击者有各种绕过方法(如编码绕过),通常作为辅助手段。
2. 输出转义/编码 (Output Encoding) —— 最重要的防御手段
在将数据输出到 HTML 页面时,将特殊字符转换为 HTML 实体。这样浏览器会将其看作普通文本,而不是代码。
需要转义的 5 个关键字符:
&-->&<--><>-->>"-->"'-->'
示例:
输入:<script>alert(1)</script>
转义后输出:<script>alert(1)</script>
浏览器会显示这段文本,但不会执行它。
3. 使用内容安全策略 (CSP - Content Security Policy)
CSP 是浏览器的一种安全机制,通过 HTTP 响应头 (Content-Security-Policy) 告诉浏览器哪些资源是合法的。
- 禁止内联脚本: 禁止
<script>...</script>和onclick="...",强制脚本必须放在外部文件中。 - 白名单机制: 只允许加载来自特定域名(如
mysite.com)的 JS 文件。 - 示例 Header:
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com;
4. 设置 Cookie 的 HttpOnly 属性
这是防止 XSS 窃取 Cookie 的最后一道防线。
如果在服务器端设置 Cookie 时加上 HttpOnly 标记,浏览器将禁止 JavaScript 读取该 Cookie(即 document.cookie 无法获取)。
虽然这不能阻止 XSS 攻击本身,但能阻止攻击者通过 XSS 盗取用户的 Session ID。
5. 使用现代前端框架
现代框架(如 React, Vue, Angular)在默认情况下会自动对数据进行转义。
- 在 React 中写
{userContent},React 会自动转义。 - 风险点: 如果你使用了强制不转义的方法(如 React 的
dangerouslySetInnerHTML或 Vue 的v-html),则必须手动确保内容的安全性(通常使用 DOMPurify 等库进行清洗)。
总结
XSS 攻击 = 攻击者在网页里插代码,坑害访问者。
防御口诀:
- 输入做检查(格式验证)。
- 输出做转义(这是关键,把
<变成<)。 - Cookie 加 HttpOnly(防盗号)。
- 开启 CSP(限制脚本来源)。
- 慎用 v-html/innerHTML(防止 DOM XSS)。