以下是一些防范CSRF攻击的有效方法:
一、使用CSRF令牌(Token)
- 令牌生成与存储
- 服务器端在用户访问包含敏感操作(如修改密码、转账等)的页面时,应生成一个唯一的、具有足够随机性的CSRF令牌。这个令牌可以通过安全的随机数生成算法来产生,例如在许多编程语言中,可以使用加密库提供的函数来生成。例如,在Python的
secrets
模块中,可以使用secrets.token_hex()
函数生成一个十六进制的随机字符串作为CSRF令牌。 - 服务器需要将生成的令牌存储在用户的会话(Session)中。会话是一种在服务器端跟踪用户状态的机制,通常与用户的登录会话相关联。这样,服务器就可以在后续的请求中验证令牌的有效性。
- 服务器端在用户访问包含敏感操作(如修改密码、转账等)的页面时,应生成一个唯一的、具有足够随机性的CSRF令牌。这个令牌可以通过安全的随机数生成算法来产生,例如在许多编程语言中,可以使用加密库提供的函数来生成。例如,在Python的
- 令牌嵌入与传递
- 在HTML表单中,将CSRF令牌嵌入到一个隐藏的表单字段中。例如:
<form action="/transfer_money" method="post"> <input type="hidden" name="csrf_token" value="123e4567 - e89b - 12d3 - a456 - 426614174000"> <input type="text" name="amount" value=""> <input type="submit" value="Transfer"> </form>
- 对于基于RESTful API的请求,也可以将令牌作为请求头的一部分传递。例如,在JavaScript中使用
fetch
函数发送请求时:const csrfToken = document.getElementsByName('csrf_token')[0].value; fetch('/api/transfer', { method: 'POST', headers: { 'Content - Type': 'application/json', 'X - CSRF - Token': csrfToken }, body: JSON.stringify({ amount: 100}) });
- 在HTML表单中,将CSRF令牌嵌入到一个隐藏的表单字段中。例如:
- 令牌验证
- 当服务器接收到请求时,会从请求中提取CSRF令牌(从表单字段或者请求头中),然后与存储在用户会话中的令牌进行比较。如果两者一致,说明请求是合法的,来自用户正常操作的页面;如果不一致或者没有令牌,则拒绝该请求,返回错误信息。
二、检查请求来源(Referer)
- 原理
- Referer头信息包含了请求的来源URL。通过检查这个头信息,服务器可以大致判断请求是否来自于合法的页面。例如,如果一个转账请求的Referer是银行网站自身的某个页面,那么这个请求很可能是合法的;但如果Referer是一个外部的、可疑的网站,就可能是CSRF攻击。
- 局限性与注意事项
- 一些用户可能会出于隐私原因禁用Referer头信息的发送,所以不能完全依赖Referer检查来防范CSRF攻击。而且,攻击者也有可能伪造Referer头信息,虽然在现代浏览器的安全机制下,伪造有一定难度,但仍然是一个潜在风险。因此,在使用Referer检查时,应该结合其他防范措施,并且要考虑到这些局限性。
三、Same - Site Cookies策略
- 属性设置与作用
- 可以将Cookies的
Same - Site
属性设置为Strict
或者Lax
。Same - Site = Strict
模式下,浏览器只会在同站点请求(即请求的URL与Cookies所属站点完全相同)中发送该Cookies。例如,对于银行网站bank.com
的Cookies,在Same - Site = Strict
模式下,只有当请求的URL也是bank.com
相关的页面时,才会发送这些Cookies。 Same - Site = Lax
模式相对宽松一些,允许在一些安全的跨站导航场景下发送Cookies,比如从外部链接点击进入网站的顶级页面时。这种模式在一定程度上平衡了安全性和用户体验,因为它允许一些常见的、相对安全的跨站操作,同时也能防止大部分的CSRF攻击。
- 可以将Cookies的
- 兼容性与实现细节
- 不同浏览器对
Same - Site
属性的支持程度有所不同,但现代主流浏览器(如Chrome、Firefox、Safari等)都已经较好地支持了该属性。在设置Same - Site
属性时,需要注意其对现有网站功能的潜在影响,特别是那些依赖跨站Cookies进行正常操作的功能,如第三方登录集成等。需要进行充分的测试,以确保网站在启用Same - Site
策略后仍然能够正常运行。
- 不同浏览器对
四、使用双重认证(2FA)
- 增加验证层
- 双重认证是在传统的用户名/密码认证基础上,增加一层额外的验证方式。例如,短信验证码、硬件令牌(如U盾)或者基于软件的身份验证器(如Google Authenticator)生成的一次性密码。
- 当用户进行敏感操作时,即使攻击者成功利用CSRF伪造了请求,由于缺少第二层验证因素,攻击仍然无法成功。例如,在转账操作中,除了常规的表单提交(可能受到CSRF攻击),还需要用户输入手机短信验证码,这样就大大增加了攻击的难度。
- 对用户体验的影响与权衡
- 双重认证会增加用户操作的步骤,在一定程度上影响用户体验。例如,用户每次登录或者进行重要操作时都需要等待短信验证码并输入,可能会感到繁琐。但是,从安全角度考虑,对于涉及重要数据和资金的应用场景,这种权衡是值得的,因为它能显著降低CSRF攻击以及其他类型攻击(如密码被盗后的非法登录)带来的风险。