跨站请求伪造(CSRF)攻击与防御详解
字数 1457 2025-11-11 12:33:05

跨站请求伪造(CSRF)攻击与防御详解

1. 什么是CSRF攻击?

跨站请求伪造(CSRF)是一种攻击方式,攻击者诱骗已登录用户在不知情的情况下执行非本意的操作。例如,用户登录银行网站后,访问恶意网站,该网站自动发送请求到银行网站进行转账操作,浏览器会携带用户的登录凭证(如Cookie)完成请求,导致恶意操作被执行。

核心条件

  1. 用户已登录目标网站(存在会话凭证)。
  2. 用户访问恶意页面(如钓鱼网站)。
  3. 目标网站未对请求来源进行严格验证。

2. CSRF攻击原理与示例

假设银行网站的转账接口如下:

POST /transfer HTTP/1.1  
Host: bank.com  
Cookie: sessionid=user123  
Content-Type: application/x-www-form-urlencoded  

amount=1000&to_account=attacker  

攻击者构造一个恶意页面,隐藏表单自动提交:

<form id="csrf" action="https://bank.com/transfer" method="POST">  
  <input type="hidden" name="amount" value="1000">  
  <input type="hidden" name="to_account" value="attacker">  
</form>  
<script>document.getElementById("csrf").submit();</script>  

当用户访问此页面时,浏览器自动携带Cookie发送POST请求,完成转账。


3. 防御CSRF的常见方法

3.1 同源策略(SOP)的局限性

浏览器同源策略限制跨域读取响应,但允许发送请求(如表单提交、图片加载),因此无法依赖SOP防御CSRF。

3.2 验证Referer头

服务器检查请求头中的Referer字段,确保请求来源是合法域名:

if request.headers.get("Referer") not in ["https://bank.com/", "https://app.bank.com/"]:  
    return "Invalid request source"  

缺陷

  • 某些浏览器或隐私设置可能不发送Referer。
  • 攻击者可能通过HTTPS→HTTP降级或Referer欺骗绕过。

3.3 使用CSRF Token

核心思想:在请求中加入攻击者无法预测的随机令牌(Token)。

实现步骤

  1. 用户访问页面时,服务器生成一个随机Token(如csrftoken=abc123),同时存储在服务端会话或Cookie中(需使用SameSite限制)。
  2. 页面表单或AJAX请求携带此Token(如隐藏字段或请求头):
    <input type="hidden" name="csrftoken" value="abc123">  
    
  3. 服务器验证请求中的Token与会话中存储的是否一致。

关键要求

  • Token需足够随机(如使用加密随机数生成器)。
  • Token与用户会话绑定,每次会话更新。
  • 敏感操作(如POST)必须验证Token。

3.4 SameSite Cookie属性

通过设置Cookie的SameSite属性,限制Cookie在跨站请求中发送:

  • SameSite=Strict:完全禁止跨站携带Cookie(可能导致用户体验问题)。
  • SameSite=Lax(默认):允许GET请求跨站携带Cookie,但阻止POST等非安全方法。
  • SameSite=None:允许跨站携带,但必须同时设置Secure(仅HTTPS)。

示例:

Set-Cookie: sessionid=user123; SameSite=Lax; Secure  

3.5 双重提交Cookie(Double Submit Cookie)

在Cookie和请求体中放置相同的随机Token,服务器验证两者是否一致。适用于无法存储服务端状态的场景(如无状态API)。


4. 进阶防御与边缘情况

4.1 Token存储位置

  • 表单隐藏字段:适用于传统Web应用。
  • 自定义HTTP头(如X-CSRF-Token):适用于AJAX请求,但需避免跨域问题(CORS需配置允许的头部)。

4.2 子域漏洞与Token范围

若应用存在多个子域(如a.bank.comb.bank.com),需确保Token严格绑定到当前子域,避免被其他子域窃取。

4.3 组合防御策略

  • 关键操作要求二次验证(如短信验证码、重新输入密码)。
  • 敏感Cookie设置HttpOnlySameSite

5. 总结

CSRF攻击依赖浏览器自动携带凭证的机制,防御核心是区分合法请求与伪造请求。推荐组合使用CSRF Token、SameSite Cookie和Referer验证,并根据业务场景选择合适策略。

跨站请求伪造(CSRF)攻击与防御详解 1. 什么是CSRF攻击? 跨站请求伪造(CSRF)是一种攻击方式,攻击者诱骗已登录用户在不知情的情况下执行非本意的操作。例如,用户登录银行网站后,访问恶意网站,该网站自动发送请求到银行网站进行转账操作,浏览器会携带用户的登录凭证(如Cookie)完成请求,导致恶意操作被执行。 核心条件 : 用户已登录目标网站(存在会话凭证)。 用户访问恶意页面(如钓鱼网站)。 目标网站未对请求来源进行严格验证。 2. CSRF攻击原理与示例 假设银行网站的转账接口如下: 攻击者构造一个恶意页面,隐藏表单自动提交: 当用户访问此页面时,浏览器自动携带Cookie发送POST请求,完成转账。 3. 防御CSRF的常见方法 3.1 同源策略(SOP)的局限性 浏览器同源策略限制跨域读取响应,但允许发送请求(如表单提交、图片加载),因此无法依赖SOP防御CSRF。 3.2 验证Referer头 服务器检查请求头中的 Referer 字段,确保请求来源是合法域名: 缺陷 : 某些浏览器或隐私设置可能不发送Referer。 攻击者可能通过HTTPS→HTTP降级或Referer欺骗绕过。 3.3 使用CSRF Token 核心思想 :在请求中加入攻击者无法预测的随机令牌(Token)。 实现步骤 : 用户访问页面时,服务器生成一个随机Token(如 csrftoken=abc123 ),同时存储在服务端会话或Cookie中(需使用SameSite限制)。 页面表单或AJAX请求携带此Token(如隐藏字段或请求头): 服务器验证请求中的Token与会话中存储的是否一致。 关键要求 : Token需足够随机(如使用加密随机数生成器)。 Token与用户会话绑定,每次会话更新。 敏感操作(如POST)必须验证Token。 3.4 SameSite Cookie属性 通过设置Cookie的 SameSite 属性,限制Cookie在跨站请求中发送: SameSite=Strict :完全禁止跨站携带Cookie(可能导致用户体验问题)。 SameSite=Lax (默认):允许GET请求跨站携带Cookie,但阻止POST等非安全方法。 SameSite=None :允许跨站携带,但必须同时设置 Secure (仅HTTPS)。 示例: 3.5 双重提交Cookie(Double Submit Cookie) 在Cookie和请求体中放置相同的随机Token,服务器验证两者是否一致。适用于无法存储服务端状态的场景(如无状态API)。 4. 进阶防御与边缘情况 4.1 Token存储位置 表单隐藏字段 :适用于传统Web应用。 自定义HTTP头 (如 X-CSRF-Token ):适用于AJAX请求,但需避免跨域问题(CORS需配置允许的头部)。 4.2 子域漏洞与Token范围 若应用存在多个子域(如 a.bank.com 和 b.bank.com ),需确保Token严格绑定到当前子域,避免被其他子域窃取。 4.3 组合防御策略 关键操作要求二次验证(如短信验证码、重新输入密码)。 敏感Cookie设置 HttpOnly 和 SameSite 。 5. 总结 CSRF攻击依赖浏览器自动携带凭证的机制,防御核心是 区分合法请求与伪造请求 。推荐组合使用CSRF Token、SameSite Cookie和Referer验证,并根据业务场景选择合适策略。