XSS原理
一、什么是 XSS 漏洞¶
XSS(Cross-Site Scripting,跨站脚本)是一种发生在**客户端浏览器层面的安全漏洞**。它的本质是:
网站没有正确处理用户输入,导致攻击者的恶意 JavaScript 被嵌入到网页中,并在其他用户的浏览器里执行。
需要注意两点:
- XSS 攻击的代码最终是在**受害者的浏览器里运行**,而不是在服务器上运行。
- 漏洞通常源自**服务器对用户输入处理不当,或前端代码使用不安全方式渲染数据**。
从危害上看,成功利用 XSS 后,攻击者通常可以:
- 读取用户的 Cookie,从而劫持登录状态
- 伪造用户操作,比如帮用户自动点赞、发帖、转账等
- 篡改页面内容,插入钓鱼界面
- 监听用户输入,窃取密码
- 在页面中植入恶意脚本,进一步传播攻击
二、XSS 漏洞的根本原理¶
理解 XSS 的关键在于:网页既包含数据,也包含可执行代码。
浏览器的工作方式是:
- 遇到普通文本,就直接显示
- 遇到
<script>之类的标签,就当作代码执行
如果网站**直接把用户输入嵌入到 HTML 中,而没有进行安全处理**,问题就出现了。
举个最简单的例子:
正常情况下,用户输入评论:
服务器返回的 HTML 可能是:
浏览器正常显示。
但如果攻击者输入:
而服务器原样输出:
浏览器看到 <script> 就会执行,这时 XSS 就发生了。
可以用一句话概括原理:
用户可控输入 + 不安全输出 + 浏览器执行 = XSS
三、XSS 的三种主要类型¶
目前业界通常将 XSS 分为三类:
- 反射型 XSS
- 存储型 XSS
- DOM 型 XSS
下面逐一说明。
1. 反射型 XSS¶
反射型 XSS 的特点是:一次性触发,不会长期存储在服务器。
典型流程是:
- 攻击者构造一个带恶意代码的链接
- 诱导受害者点击
- 服务器接收到参数后,未经过滤直接返回给浏览器
- 浏览器解析页面并执行恶意脚本
之所以叫“反射型”,是因为服务器只是把用户输入“反射回来”,本身并没有保存它。
常见场景包括:
- 搜索结果页
- 错误提示页
- 参数回显页面
例如:
如果服务器直接把 q 的内容展示出来,就可能触发反射型 XSS。
2. 存储型 XSS¶
存储型 XSS 是**危害最大的一种类型**,因为恶意代码会被长期保存在服务器上。
典型流程是:
- 攻击者在评论区、论坛、个人资料页提交恶意代码
- 服务器把内容存入数据库
- 其他用户访问页面时,服务器把含有恶意代码的内容取出并展示
- 所有访问该页面的用户都会中招
典型场景包括:
- 论坛评论
- 博客留言
- 社交媒体帖子
- 在线协作文档
- 用户个人资料
危险之处在于:
- 一次攻击,可能影响成千上万用户
- 不需要诱导点击,只要访问页面就会触发
- 攻击可以长期存在
3. DOM 型 XSS¶
DOM 型 XSS 与前两种不同,它的关键点是:漏洞主要出在前端 JavaScript 代码,而不是服务器。
在这种情况下,服务器可能是安全的,但前端代码处理数据的方式不安全。
例如:
如果用户访问:
浏览器会把 hash 里的内容插入页面并执行,而服务器根本没有参与处理。
这种类型在现代单页应用(SPA)中比较常见,比如使用 Vue、React、原生 JavaScript 的前端页面。
四、三种 XSS 的对比¶
从性质上看:
- 反射型:临时、一次性,需要诱导点击
- 存储型:长期存在、自动触发,危害最大
- DOM 型:主要由前端代码问题导致
从责任方看:
- 反射型和存储型主要是服务器处理不当
- DOM 型主要是前端开发方式不安全
五、从原理理解为什么会发生 XSS¶
XSS 之所以频繁出现,主要有三个原因:
第一,开发者习惯直接拼接 HTML,例如:
第二,服务器对用户输入没有做充分的转义或过滤。
第三,浏览器本身的机制是“看到脚本就执行”,只要页面里出现恶意脚本,它就会运行。
六、简单的防御思路¶
理解原理后,防御逻辑也会变得清晰:
- 不要把用户输入直接当作 HTML 解析。
- 在输出到页面前,对特殊字符进行转义,比如把
<变成<。 - 尽量使用安全的前端 API,例如
textContent而不是innerHTML。 - 对重要网站开启 Content-Security-Policy(CSP),限制脚本来源。