跨站请求伪造(CSRF)攻击与防御详解
字数 1795 2025-11-11 23:11:13
跨站请求伪造(CSRF)攻击与防御详解
1. 什么是CSRF攻击?
CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种恶意攻击,攻击者诱导用户在当前已登录的Web应用中执行非本意的操作。例如,用户登录银行网站后,访问恶意网站,该网站自动发送请求到银行网站进行转账(利用用户已保存的登录状态)。
关键条件:
- 用户已登录目标网站(存在会话Cookie)。
- 用户访问恶意网站或页面,该页面自动发送请求至目标网站。
- 目标网站未验证请求的来源(缺乏CSRF防护)。
2. CSRF攻击原理与示例
攻击流程:
- 用户登录目标网站(如
bank.com),服务器返回会话Cookie(如session_id=abc)。 - 用户访问恶意网站(如
evil.com),该网站隐藏了一个自动提交的表单:<form action="https://bank.com/transfer" method="POST"> <input type="hidden" name="to_account" value="attacker"> <input type="hidden" name="amount" value="1000"> </form> <script>document.forms[0].submit();</script> - 浏览器自动携带Cookie发送请求:用户访问
evil.com时,浏览器自动向bank.com/transfer发送POST请求,并附带已保存的会话Cookie。 - 服务器误认为用户自愿操作:因请求包含合法Cookie,服务器执行转账。
常见攻击方式:
- GET请求CSRF:通过
<img src="https://bank.com/transfer?to=attacker&amount=1000">自动触发。 - POST请求CSRF:通过隐藏表单自动提交。
- 其他HTTP方法:需结合JavaScript(如Fetch API),但受同源策略限制(需CORS允许)。
3. 防御CSRF攻击的方法
(1)同源检测(Origin/Referer验证)
- 检查
Referer头:服务器验证请求的Referer头是否来自合法域名(如仅允许bank.com)。- 缺点:部分浏览器或隐私设置可能不发送
Referer。
- 缺点:部分浏览器或隐私设置可能不发送
- 检查
Origin头:对POST/CORS请求,检查Origin头是否合法(更可靠)。
(2)CSRF Token(最常用)
原理:
- 用户访问页面时,服务器生成一个随机Token(如
csrftoken=abc123),同时保存在服务端(如Session)和页面表单(或Meta标签)中。 - 用户提交请求时,必须携带Token(如通过表单隐藏字段或请求头)。
- 服务器验证Token是否匹配。
示例:
<!-- 表单中嵌入Token -->
<form action="/transfer" method="POST">
<input type="hidden" name="csrftoken" value="abc123">
...
</form>
关键要求:
- Token需随机且不可预测(使用加密安全随机数生成器)。
- 对敏感操作(如POST、PUT)强制验证。
- Token与用户会话绑定,每次会话或请求更新。
(3)双重Cookie验证
- 请求时从Cookie中读取Token,并额外通过请求参数或头(如
X-CSRF-Token)发送该Token。 - 服务器比较两者是否一致。
- 注意:需防范子域名劫持(确保Cookie的SameSite属性设置)。
(4)SameSite Cookie属性
- 设置Cookie的
SameSite属性为Strict或Lax:Strict:仅同站请求携带Cookie(完全阻止CSRF,但可能影响用户体验)。Lax:允许部分安全请求(如GET)携带Cookie,阻止非安全跨站请求(如POST)。
- 现代浏览器默认将Cookie设为
Lax。
4. 进阶场景与绕过技术
(1)Token保护被绕过的情况
- Token泄露:若存在XSS漏洞,攻击者可窃取Token。
- Token未绑定会话:若Token全局通用或可预测,可能被爆破。
- 验证逻辑缺陷:如仅检查Token存在性而非有效性。
(2)SameSite Cookie的局限性
- 部分旧浏览器不支持。
Lax模式允许GET请求携带Cookie,需避免用GET执行敏感操作。
(3)结合其他攻击(如XSS)
- 若网站存在XSS漏洞,攻击者可直接获取Token或伪造请求,CSRF防护失效。
5. 最佳实践总结
- 敏感操作用POST:避免用GET执行状态变更操作。
- 强制使用CSRF Token:对所有状态变更请求验证Token。
- 设置SameSite Cookie:补充防御。
- 避免Token泄露:结合XSS防护措施。
- 关键操作二次验证:如要求重新输入密码或短信验证码。
通过以上多层防护,可有效抵御CSRF攻击。