xss攻击复习总结

【安全研发】XSS (跨站脚本攻击) 深度复盘与实战笔记

记录时间: 2026-01-20
核心逻辑: 永远不要相信用户的输入。 必须严格区分 数据 (Data) 与 代码 (Code)。


1. 核心原理:什么是 XSS?

Cross Site Scripting。本质是黑客把恶意的 JavaScript 代码注入到了我的网页里,当受害者访问时,浏览器误以为那是正常的代码去执行了。

攻击后果:

  • 偷取 Cookie / SessionID(导致账号被盗)。
  • 监听用户键盘输入。
  • 伪造用户操作(如自动转账)。

2. 三大攻击类型(记忆口诀)

类型 存储位置 危险等级 攻击原理速记
存储型 (Stored) 数据库 ⭐⭐⭐⭐⭐ (最高) 恶意代码存入 DB。一人发帖,万人中招。持久化攻击。
反射型 (Reflected) URL参数 ⭐⭐⭐ 恶意代码在链接里。需要诱导用户点击链接,后端把参数"反射"回页面。
DOM 型 (DOM-based) HTML DOM ⭐⭐⭐ 纯前端漏洞。后端不背锅。JS 代码乱改页面结构导致执行脚本。

3. 实战:DOM 型 XSS 的"帮凶"们

这是今天复习的重点,涉及两个关键 API:document.write 和 URLSearchParams。

3.1 漏洞代码演示 (document.write)

document.write 是上古时代的 API,它有两个致命问题:

  1. 逻辑炸弹: 如果页面加载完后调用,会清空整个页面。
  2. 安全黑洞: 直接解析 HTML 字符串,如果包含 <script> 会被执行。

攻击场景复现:

javascript 复制代码
// 1. 现代化的获取 URL 参数方式 (记忆点:URLSearchParams)
// 假设 URL 是:http://localhost/index.html?name=<script>alert(document.cookie)</script>
const params = new URLSearchParams(window.location.search);
const userName = params.get("name"); // 拿到了恶意脚本字符串

// 2. 致命错误:直接写入 DOM
// 浏览器会把 userName 当作 HTML 解析,发现里面有 script 标签,于是执行!
if (userName) {
    document.write("欢迎你:" + userName); 
}

3.2 为什么 URLSearchParams 这么顺手?

它是 ES6 后的原生 API,替代了以前复杂的正则匹配。

  • params.get("key"): 获取值。
  • params.has("key"): 判断存在。
  • 正因为它获取参数太容易,如果开发者拿到参数后不做 HTML 转义 就渲染,XSS 就发生了。

4. 防御体系:如何把"代码"变成"文本"?

4.1 核心防御:HTML 转义 (Escaping)

让浏览器**"只读其文,不从其令"**。

  • 攻击者输入: <script>alert(1)</script>
  • 后端/前端转义后: &lt;script&gt;alert(1)&lt;/script&gt;
  • 浏览器渲染结果: 屏幕上显示出 <script>... 这行字,但不执行它。

4.2 其他防御层

  • HttpOnly Cookie: 给敏感 Cookie 加上 HttpOnly 属性,让 JS 读不到(document.cookie 读出来是空的),防止 Token 被偷。
  • CSP (内容安全策略): 在 HTTP 头里限制浏览器只能加载特定域名的 JS 文件,禁止内联脚本。

5. 灵魂 Q&A (今日复盘总结)

Q1: XSS 是不是只要把 < 和 > 转义了就安全了?

A: 90% 的情况是。但在某些特殊属性(如 href 或 onclick)里,还需要注意引号的转义,防止属性逃逸。

Q2: 既然 document.write 这么危险,为什么还有人用?

A: 主要是老旧代码或第三方广告脚本在用。现代开发(Vue/React)几乎不用它,而是用虚拟 DOM。但如果用了 v-html 或 dangerouslySetInnerHTML,依然会有 XSS 风险。

Q3: 遇到存入数据库的 XSS(存储型),是在"入库时"转义,还是"出库显示时"转义?

A: 最佳实践是"出库显示时"转义。

  • 入库保留原始数据(Raw Data),保证数据的纯洁性(万一以后要用于非 HTML 场景呢?)。
  • 谁显示,谁负责转义(Context-Aware Encoding)。

(End of Notes - 2026.01.20 晚)

相关推荐
lpfasd1233 小时前
node-sass 停止维护!老项目迁移 Dart Sass 完整教程
前端·rust·sass
Data analyse4566 小时前
rnweb 回放数据量太大怎么办?分片存储与断点续传的实现思路
前端·网络·算法·数据分析
xiaogai_gai6 小时前
金蝶收料通知单查询策略实战教程:从源系统拉取到中间层落地的完整路径
java·前端·数据库
环境栈笔记7 小时前
指纹浏览器 WebRTC 怎么设置?从 ICE 候选、代理出口到功能验证
前端·人工智能·后端·自动化
赵大仁7 小时前
官网性能优化实战:LCP 3.2s → 2.1s、CLS 0.107 → 0,以及被我推翻的 6 个判断
前端·性能优化·cls·lcp·core web vitals
xiancai_xianyu7 小时前
Text2SQL落地生产库前,SQL要过哪三道闸
前端·数据库·sql·sql注入·text2sql·ai agent开发·企业级ai框架
小羊没烦恼!8 小时前
T-SQL查询进阶--理解SQL SERVER中的分区表
服务器·开发语言·前端·javascript·html
史瓦辛格8 小时前
给 DeepSeek Harness 写费用插件:把「这次会话花了多少钱」算准
前端·deepseek
星光不问赶路人8 小时前
Vue 3 + TypeScript 中 enum 的使用实践
前端·vue.js
鸥梨菌Honevid8 小时前
UVM 中 REQ 和 RSP 类型详解:从通信模型到 item_done 与 put_response
java·前端·servlet