# 13. XSS、CSRF区别

# 1. XSS

Cross-Site Scripting(跨站脚本攻击)简称 XSS,是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全。实现xss攻击具备2个条件,第一需要向web页面注入恶意的代码,第二,这些恶意代码被浏览器成功的执行。

# 攻击类型

根据攻击的来源,XSS 攻击可分为存储型、反射型和 DOM 型三种。

存储型

  1. 攻击者将恶意代码提交到目标网站的数据库中。
  2. 用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在 HTML 中返回给浏览器。
  3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
  5. 这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。

反射型 XSS

  1. 攻击者构造出特殊的 URL,其中包含恶意代码。
  2. 用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。
  3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
  5. 反射型 XSS 跟存储型 XSS 的区别是:存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里。

反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。

由于需要用户主动打开恶意的 URL 才能生效,攻击者往往会结合多种手段诱导用户点击。

POST 的内容也可以触发反射型 XSS,只不过其触发条件比较苛刻(需要构造表单提交页面,并引导用户点击),所以非常少见。

DOM 型 XSS

  1. 攻击者构造出特殊的 URL,其中包含恶意代码。
  2. 用户打开带有恶意代码的 URL。
  3. 用户浏览器接收到响应后解析执行,前端 JavaScript 取出 URL 中的恶意代码并执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。

# 预防

XSS 攻击有两大要素:

  1. 攻击者提交恶意代码。
  2. 浏览器执行恶意代码。

如果是前端过滤的,攻击者直接绕过前端发送请求就可以提交恶意代码了。
如果是后端插入数据库前过滤的,则并不知道内容输出到哪里,不同位置编码可能会不同,可能会造成乱码问题。

所以输入过滤并不可靠。

预防存储型和反射型XSS攻击有两种常见做法:

  1. 改成纯前端渲染,把代码和数据分隔开。
  2. 对HTML做转义 & < > " ' /

预防 DOM 型 XSS 攻击
DOM 型 XSS 攻击,实际上就是网站前端 JavaScript 代码本身不够严谨,把不可信的数据当作代码执行了。

在使用 .innerHTML、.outerHTML、document.write() 时要特别小心。eval()、setTimeout()、setInterval() 等,都能把字符串作为代码运行。

启用CSP。

# XSS 的检测

  1. 手动利用XSS攻击字符串进行检测。
  2. 利用XSS漏洞扫描工具进行扫描。

xss攻击

# 2. CSRF

你向同一个服务器发请求时会带上浏览器保存的对于那个服务器的cookie,而不管你从哪个网站发请求

CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。

以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账……造成的问题包括:个人隐私泄露以及财产安全。

一个典型的CSRF攻击有着如下的流程:

  1. 受害者登录a.com,并保留了登录凭证(Cookie)。
  2. 攻击者引诱受害者访问了b.com。
  3. b.com 向 a.com 发送了一个请求:a.com/act=xx。浏览器会默认携带a.com的Cookie。
  4. a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。
  5. a.com以受害者的名义执行了act=xx。
  6. 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。

# 攻击类型

  1. GET类型的CSRF:访问含有img的页面自动发送GET请求。
  2. POST类型的CSRF:自动提交表单。
  3. 链接类型的CSRF:比如论坛中发布的图片嵌入链接,用户点击就会将认证信息带过去。

# 预防

  1. CSRF(通常)发生在第三方域名。

  2. CSRF攻击者不能获取到Cookie等信息,只是使用。攻击者无法直接窃取到用户的信息(Cookie,Header,网站内容等),仅仅是冒用Cookie中的信息。

  3. CSRF自动防御策略:同源检测(Origin 和 Referer 验证)。

  4. CSRF主动防御措施:Token验证(利用了CSRF无法获取到Cookie信息) 或者 双重Cookie验证(两个sessionid,请求时将一个拼接到url后面,后台比较url参数和另一个session是否相等,利用了CSRF无法获取到Cookie信息) 以及配合Samesite Cookie。

  5. 保证页面的幂等性,后端接口不要在GET页面中做用户操作。

# 3. CSRF和XSS的区别

  1. CSRF需要登录,冒用COOKIE,利用网站本身的漏洞,去请求网站的api
  2. XSS,不需要登录,向网站注入JS代码,执行JS里的代码,篡改网站的内容

# 4. 参考

前端安全系列(一):如何防止XSS攻击? (opens new window) 前端安全系列之二:如何防止CSRF攻击? (opens new window)

攻击方式 一句话概括 攻击目标 攻击方向
XSS(跨站脚本攻击) “你在我的页面里执行了恶意代码” 用户(窃取用户数据) 攻击者 → 用户
CSRF(跨站请求伪造) “你借用我的身份去执行了操作” 网站(冒充用户操作) 用户 → 网站(被利用)

# 二、XSS(跨站脚本攻击)

# 核心原理

XSS 是指攻击者往网页中注入恶意脚本,当用户浏览该页面时,脚本就会在用户浏览器中执行。

攻击流程:

1. 攻击者在评论区提交恶意脚本
   &lt;script>document.cookie&lt;/script>

2. 服务器没有过滤,存储到了数据库

3. 正常用户访问页面,浏览器执行该脚本
   → 攻击者窃取了用户的 Cookie/Token
1
2
3
4
5
6
7

# 攻击类型

类型 说明 示例
反射型 XSS 恶意脚本通过 URL 参数传递,后端直接输出到页面 https://site.com/search?q=<script>alert(1)</script>
存储型 XSS 恶意脚本存储在服务器(如评论区、留言板),访问时执行 在评论区提交 <script>fetch('/api/user')</script>
DOM 型 XSS 恶意脚本通过修改 DOM 结构触发,不经过服务器 从 URL 取参数,用 innerHTML 渲染

# 防御方案

// ✅ 1. 输出时转义(最重要!)
function escapeHtml(str) {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#x27;')
}

// ✅ 2. 不使用 innerHTML,用 textContent
element.textContent = userInput   // ✅ 安全
element.innerHTML = userInput     // ❌ 危险

// ✅ 3. HTTP-only Cookie
// 设置 Cookie 时加 HttpOnly 属性,禁止 JS 读取
Set-Cookie: sessionId=xxx; HttpOnly; Secure

// ✅ 4. CSP(内容安全策略)
// 限制只允许加载同源脚本
Content-Security-Policy: script-src 'self'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 三、CSRF(跨站请求伪造)

# 核心原理

CSRF 是指攻击者利用用户已经登录的身份,在用户不知情的情况下,诱导用户发送恶意请求。

攻击流程:

1. 用户登录了银行网站 A,Cookie 未过期
2. 攻击者在恶意网站 B 中嵌入:
   &lt;img src="https://bank.com/transfer?to=attacker&amp;amount=1000">
3. 用户访问网站 B,浏览器自动带上 A 的 Cookie
4. 银行服务器收到请求,以为用户本人操作 → 转账成功
1
2
3
4
5

# 关键条件

✅ 用户已登录目标网站(Cookie 有效)
✅ 目标网站的 Cookie 没有 SameSite 限制
✅ 攻击者能预测请求的 URL 和参数(GET 型)或诱导用户提交表单(POST 型)
1
2
3

# 防御方案

// ✅ 1. CSRF Token(最常用)
// 在表单中埋入随机 Token,服务器验证
<form>
  <input type="hidden" name="csrf_token" value="随机字符串">
  <input type="text" name="amount">
  <button>转账</button>
</form>

// ✅ 2. SameSite Cookie(推荐!)
// 设置 Cookie 的 SameSite 属性
Set-Cookie: sessionId=xxx; SameSite=Strict
// Strict:只有同源请求才携带 Cookie
// Lax:只允许 GET 导航到目标地址时携带

// ✅ 3. 验证 Referer 头
// 服务器检查请求来源是否为同源

// ✅ 4. 关键操作使用 POST,配合 CSRF Token
// GET 请求容易被 img 标签等跨站发起
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 四、XSS vs CSRF 核心对比

对比维度 XSS CSRF
攻击者目标 窃取用户数据(Cookie、Token、个人信息) 冒充用户执行操作(转账、发消息、修改密码)
攻击方式 向页面注入恶意脚本 诱导用户发起请求(利用已登录状态)
受害者 浏览器使用者(脚本在用户浏览器执行) 网站服务器(请求是从用户浏览器发出)
是否需要用户执行 用户访问页面即可触发 用户点击链接或访问恶意网站
防御重点 输入过滤 + 输出转义 请求来源验证 + Token + SameSite

# 一句话区别

XSS 是代码注入攻击,攻击者直接在你的页面里执行恶意脚本;CSRF 是身份冒用攻击,攻击者利用你的身份,在你不操作时替你发请求。

# 五、面试回答话术

XSS 和 CSRF 是 Web 安全中最常见的两种攻击方式,它们的区别体现在三个方面:

1. 攻击目标不同

  • XSS 攻击的是用户,目的是窃取用户的数据(Cookie、Token、个人信息)
  • CSRF 攻击的是网站,目的是冒充用户执行非法操作(转账、删数据)

2. 攻击方式不同

  • XSS 通过注入恶意脚本到页面,用户访问时自动执行
  • CSRF 通过诱导用户发送请求,利用已登录的身份

3. 防御方向不同

  • 防御 XSS 靠的是输入验证 + 输出转义,以及设置 HttpOnly Cookie
  • 防御 CSRF 靠的是CSRF Token、SameSite Cookie、验证 Referer 头

两者也有关系:如果一个网站有 XSS 漏洞,攻击者可以利用 XSS 窃取到 CSRF Token,从而绕过 CSRF 防御。所以先防 XSS,再防 CSRF,是安全防御的基本顺序。

# 六、实际防御示例

# 在 Vue 项目中的防御

// 1. Vue 模板中的 XSS 防御
// Vue 默认会对 {{ }} 中的内容进行转义,防止 XSS
<div>{{ userInput }}</div>  // ✅ 安全,Vue 自动转义

// ❌ 危险:使用 v-html 时需确保内容可信
<div v-html="trustedHtml"></div>  // ⚠️ 只有可信内容才用

// 2. 接口请求携带 CSRF Token
// axios 拦截器
axios.interceptors.request.use(config => {
  // 从 Cookie 或 meta 标签读取 CSRF Token
  const token = document.querySelector('meta[name="csrf-token"]').content
  config.headers['X-CSRF-Token'] = token
  return config
})

// 3. 设置 Cookie 的属性(服务端)
// httpOnly: 禁止 JS 读取
// SameSite: 限制跨站请求携带 Cookie
// Secure: 仅 HTTPS 传输
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 七、记忆口诀

XSS → 脚本注入偷数据
CSRF → 身份冒用搞破坏

防 XSS:转义 + HttpOnly + CSP
防 CSRF:Token + SameSite + Referer

先防 XSS,再防 CSRF!
1
2
3
4
5
6
7