CSRF:告别面试题CSRF困扰 🤔

5 阅读7分钟

还在死记硬背CSRF?是时候真正理解它了!本文清晰剖析CSRF攻击的来龙去脉,总结了多种主流解决方案及其优缺点

来熟悉一下吧

CSRF和XSS的区别?

CSRF(跨站请求伪造):利用用户身份发送请求,不需要获取用户信息,攻击的是用户的操作

XSS(跨站脚本攻击):注入恶意脚本到页面,可以获取用户敏感信息,攻击的是用户的数据

什么是csrf攻击

CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种网络攻击方式,攻击者诱导用户在已登录的网站上执行非本意的操作。简单来说:攻击者利用用户的身份(如已登录的cookie),冒充用户发送恶意请求。

CSRF 攻击的本质是利用 cookie 会在同源请求中携带发送给服务器的特点,以此来实现用户的冒充

cookie的作用域是基于域名的,浏览器会根据请求的域名来决定是否发送cookie,以及发送哪些cookie。因此,即使请求是由B网站伪造的,只要请求的域名是A网站,浏览器就会发送与A网站相关的cookie

CSRF攻击的流程

  1. 用户登录受信任意网站A,浏览器保存登录Cookie
  2. 用户访问恶意网站B(浏览器保有A网站登录的状态)
  3. 恶意网站B想向网站A发起请求,浏览器自动携带Cookie
  4. 网站A误以为是用户的正常操作,执行了恶意请求

示例:

<!-- 恶意网站的代码 -->
<img src="http://bank.com/transfer?amount=999&to=ZhanSan" />
<form action="http://bank.com/transfer" method="POST">
  <input type="hidden" name="amount" value="999" />
  <input type="hidden" name="to" value="ZhanSan" />
</form>

这段代码就会在用户访问恶意网站的时候,自动向银行网站发起请求,从而完成转账(网站没有做好防御)

成本不要太低,只要诱导用户点击恶意网站的地址,就这么一小段代码,就能完成攻击。2010年左右是真要小心xx在线发牌、男人听了沉默女人听了流泪等诱导广告😄

查询了一下csrf最猖獗的时候是2010年左右,有以下的背景:

  1. 早期Web应用的状态管理严重依赖Cookie:当时,大多数网站使用Cookie来验证用户身份和维持会话。CSRF恰好利用了浏览器自动携带Cookie的特性。

  2. 缺乏统一的防护标准:像CSRF Token、SameSite Cookie属性等有效的防护手段尚未普及,或者浏览器的支持不完善。很多开发者甚至没有意识到CSRF的风险,或者不知道如何正确防御。

  3. Web 2.0应用的兴起:随着社交网络、在线银行、电子商务等交互式应用的普及,用户在登录状态下可以执行的操作越来越多(如发帖、转账、购物),这使得CSRF攻击的潜在危害和吸引力也随之增大。攻击者可以通过简单的图片链接或表单就能诱导用户执行敏感操作。

解决方案

1. CSRF Token

CSRF Token 是服务器生成的一个随机字符串,只有真正的用户页面才能获取到 工作原理:

<!-- 服务器在页面中嵌入Token -->
 <meta name="csrf-token" content="1a2c3d">

前端发送请求是必须携带这个Token,服务器会进行验证

const token = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
fetch(url, {
  method: "POST",
  headers: {
    'Content-Type': 'application/json',
    'X-CSRF-TOKEN': token
  },
  body: JSON.stringify({
    amount: 100,
    to: 'ZhanSan'
  })
})

为什么有效??

  • 恶意网站无法获取到其他网站页面中的Token
  • 没有正确的Token,服务器会拒绝请求

✅ 优势

  • 安全性高:攻击者无法获取其他域名页面中的Token
  • 成熟稳定:被广泛验证的防护方案
  • 框架支持好:主流框架都有内置支持
  • 兼容性好:支持所有浏览器

❌ 缺点

  • 开发复杂度高:需要在每个表单和Ajax请求中添加Token
  • 维护成本高:Token失效需要重新获取,增加错误处理逻辑

2. SameSite Cookie (浏览器原生防护)

从csrf攻击的原理中可知,攻击者会诱导你点击一个恶意链接进入到一个恶意网站,它和被攻击网站不同域名

但浏览器会根据请求的域名来决定是否发送cookie,即使当前处于恶意网站,但请求的域名是银行网站,浏览器会发送银行网站的cookie,从而导致csrf攻击

那么阻止跨域的网站里面发起的请求获取cookie即可

而SameSite Cookie可控制Cookie在跨域请求是否发送

它有下面三种模式:

Strict模式(最严格): 仅允许同源请求发送Cookie

document.cookie = 'sessionId=abc123; SameSite=Strict'
  • 完全禁止跨站发送Cookie
  • 即使用户点击链接跳转也不发送

Lax模式(默认): 允许同源请求和跨域请求发送Cookie

document.cookie = 'sessionId=abc123; SameSite=Lax'
  • 大部分跨站请求不发送Cookie
  • 但用户点击链接导航到目标网站时会发送,get方式的表单提交会发送,预加载链接会发送
  • 平衡了安全性和用户体验

会发送cookie:

<!-- 1. 用户点击链接 -->
<a href="https://bank.com/dashboard">银行首页</a>

<!-- 2. GET方式的表单提交 -->
<form method="GET" action="https://bank.com/search">
    <input name="query" value="余额">
    <button type="submit">搜索</button>
</form>

<!-- 3. 预加载链接 -->
<link rel="prerender" href="https://bank.com/dashboard">

不会发送cookie:

<!-- 1. POST/PUT/DELETE等请求 -->
<form method="POST" action="https://bank.com/transfer">
    <input name="amount" value="1000">
</form>

<!-- 2. iframe加载 -->
<iframe src="https://bank.com/widget"></iframe>

<!-- 3. Ajax请求 -->
<script>
fetch('https://bank.com/api/balance');
</script>

<!-- 4. 图片/脚本等资源请求 -->
<img src="https://bank.com/avatar.jpg">

✅ 优势

  • 配置简单:只需要设置Cookie属性
  • 浏览器原生支持:无需额外代码逻辑
  • 性能优异:几乎无性能开销
  • 自动防护:不需要每个请求都处理

❌ 缺点

  • 兼容性问题:老版本浏览器不支持
  • 灵活性差:难以针对特定业务场景调整
  • 功能限制:Strict模式可能影响正常跳转
  • HTTPS依赖:None模式必须在HTTPS下工作

对cookie 进行双重验证

服务器在用户访问网站页面时,向请求域名注入一个Cookie,内容为随机字符串,然后当用户再次向服务器发送请求的时候,从 cookie 中取出这个字符串,添加到 URL 参数中,然后服务器通过对 cookie 中的数据和参数中的数据进行比较,来进行验证。使用这种方式是利用了攻击者只能利用 cookie,但是不能访问获取 cookie 的特点。并且这种方法比 CSRF Token 的方法更加方便,并且不涉及到分布式访问的问题。这种方法的缺点是如果网站存在 XSS 漏洞的,那么这种方式会失效

✅ 优势

  • 无状态验证:服务器不需要存储Token状态
  • 水平扩展友好:适合分布式系统
  • 实现相对简单:比传统CSRF Token简单
  • 自动过期:随Cookie过期自动失效

❌ 缺点

  • 安全性稍弱:在某些攻击场景下可能被绕过
  • Cookie依赖:完全依赖Cookie机制
  • 调试复杂:需要同时检查Cookie和请求参数
  • XSS风险:如果存在XSS漏洞,此方法无效

3. Referer/Origin 验证

前置知识点:HTTP中Origin和Referer的区别?

检查HTTP请求头中的Referer或Origin字段,验证请求来源是否为允许访问的域名,从而对请求进行过滤。当Referer/Origin字段为空时,则认为是非法请求,不进行处理

✅ 优势

  • 实现简单:只需要检查HTTP头部
  • 性能优异:验证逻辑简单快速
  • 无客户端依赖:不需要前端特殊处理
  • 实时生效:立即生效,无需刷新

❌ 缺点

  • 可以被绕过:用户可能禁用Referer发送(<meta name="referrer" content="never">
  • 代理影响:某些代理可能修改或删除这些头部
  • HTTPS限制:HTTPS到HTTP的跳转不会发送Referer

总结

安全问题少有遇到,现在大部分都是使用的token的方式做到的登录状态的保持,所以很少遇到csrf攻击,但是面试官喜欢问,那么咱学习一下 🤓

一个浏览器的策略问题导致了这么多的解决方案,设计cookie的大佬也是没想到有这样的漏洞,遇到问题就解决问题好了