跨站请求伪造(CSRF)攻击与防御详解
字数 1457 2025-11-11 12:33:05
跨站请求伪造(CSRF)攻击与防御详解
1. 什么是CSRF攻击?
跨站请求伪造(CSRF)是一种攻击方式,攻击者诱骗已登录用户在不知情的情况下执行非本意的操作。例如,用户登录银行网站后,访问恶意网站,该网站自动发送请求到银行网站进行转账操作,浏览器会携带用户的登录凭证(如Cookie)完成请求,导致恶意操作被执行。
核心条件:
- 用户已登录目标网站(存在会话凭证)。
- 用户访问恶意页面(如钓鱼网站)。
- 目标网站未对请求来源进行严格验证。
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)。
实现步骤:
- 用户访问页面时,服务器生成一个随机Token(如
csrftoken=abc123),同时存储在服务端会话或Cookie中(需使用SameSite限制)。 - 页面表单或AJAX请求携带此Token(如隐藏字段或请求头):
<input type="hidden" name="csrftoken" value="abc123"> - 服务器验证请求中的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.com和b.bank.com),需确保Token严格绑定到当前子域,避免被其他子域窃取。
4.3 组合防御策略
- 关键操作要求二次验证(如短信验证码、重新输入密码)。
- 敏感Cookie设置
HttpOnly和SameSite。
5. 总结
CSRF攻击依赖浏览器自动携带凭证的机制,防御核心是区分合法请求与伪造请求。推荐组合使用CSRF Token、SameSite Cookie和Referer验证,并根据业务场景选择合适策略。