CSRF攻击的原理与防御手段
什么是CSRF攻击?
CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种常见的网络安全攻击方式,攻击者利用用户已经通过认证的身份在受信任网站上执行未经用户授权的操作。
CSRF攻击原理
CSRF 攻击的一般过程如下:
用户登录受信任网站 A,并在浏览器中保持了登录状态。
用户访问恶意网站 B。
恶意网站 B 中的页面中包含针对网站 A 的请求(例如,提交表单或发送 AJAX 请求)。
用户在不知情的情况下,这些请求会被发送到受信任网站 A,因为浏览器会自动添加用户在网站 A 上的身份认证信息。
受信任网站 A 接收到请求后,会将其视为用户的有效请求并执行相应的操作,例如更改密码、发表评论等。
由此可知,要完成一次CSRF攻击,受害者必须依次完成两个步骤:
- 登录受信任网站A,并在本地生成Cookie。
- 在不登出A的情况下,访问危险网站B。
看到这里,你也许会说:“如果我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生:
1.你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站。
2.你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了......)
3.上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。
CSRF的主要防御方法
同源检测
Cookie的同源和浏览器的同源策略有所区别:
浏览器同源策略:协议、域名和端口都相同即同源;
Cookie同源策略:域名相同即同源;
在HTTP协议中,每个异步请求都会携带两个header,用来标记来源域名:
Origin Header
Referer Header
这两个Header在浏览器发起请求时,大多数情况会自动带上,并且不能由前端修改,服务器接收到后可以根据这两个Header确定来源的域名;
特殊情况: 如果Origin和Referer都不存在,建议直接进行阻止,特别是如果在没有使用随机CSRF Token作为第二次检查。
另外,CSRF大多数情况下来自第三方域名,但并不能排除本域发起。如果攻击者有权限在本域发布评论(含链接、图片等),那么它可以直接在本域发起攻击,这种情况下同源策略无法达到防护的作用。
综上所述:同源验证是一个相对简单的防范方法,能够防范绝大多数的CSRF攻击。但这并不是万无一失的,对于安全性要求较高,或者有较多用户输入内容的网站,我们就要对关键的接口做额外的防护措施。
CSRF token
CSRF攻击之所以能够成功是因为服务器把攻击者携带的Cookie当成了正常的用户请求,那么我们可以要求所有用户请求都携带一个无法被攻击者劫持的token,每次请求都携带这个token,服务端通过校验请求是否为正确token,可以防止CSRF攻击。
CSRF token的防护策略分为三步:
1. 将token输出到页面:首先,用户打开页面的时候,服务器需要给这个用户生成一个Token,该Token通过加密算法对数据进行加密,一般Token都包括随机字符串和时间戳的组合,显然在提交时Token不能再放在Cookie中了,否则又会被攻击者冒用。
2. 请求中携带token:对于GET请求,将token附在请求地址之后,如:http://url?token=tokenValue 对于POST请求,要在Form表单后面加上
<input type=”hidden” name=”token” value=”tokenvalue”/>
3. 服务端验证token是否正确:服务端拿到客户端给的token后,先解密token,再比对随机字符串是否一致、时间是否有效,如果字符串对比一致且在有效期内,则说明token正确。
referer和token谁更安全?
referer和token谁安全等级高?
token安全等级更高,因为并不是任何服务器都可以取得referer,如果从HTTPS跳到HTTP,也不会发送referer。并且FLASH一些版本中可以自定义referer。
但是token的话,要保证其足够随机且不可泄露。(不可预测性原则)
referer如何验证?
对header中的referer的验证,一个是空referer,一个是referer过滤或者检测不完善。
为了杜绝这种问题,在验证的白名单中,正则规则应当写完善。
token如何验证?
引用一段请教前辈的回答:
针对token的攻击,一是对它本身的攻击,重放测试一次性、分析加密规则、校验方式是否正确等,二是结合信息泄露漏洞对它的获取,结合着发起组合攻击
信息泄露有可能是缓存、日志、get,也有可能是利用跨站
很多跳转登录的都依赖token,有一个跳转漏洞加反射型跨站就可以组合成登录劫持了
另外也可以结合着其它业务来描述token的安全性及设计不好怎么被绕过比如抢红包业务之类的
对token的检查和验证应该与其他漏洞的防御相结合,如XSS攻击,因为针对token的攻击往往是与其他漏洞一起利用的。
Samesite Cookie属性
Chrome 51版本 开始,浏览器的 Cookie 新增加了一个SameSite属性,用来防止 CSRF 攻击。
Cookie的Samesite属性用来限制第三方Cookie, 从而减少安全风险,它有三个值:
Set-Cookie: SameSite = Strict;
Set-Cookie: SameSite = Lax;
Set-Cookie: SameSite = None;
Strict: 最为严格,完全禁止第三方Cookie, 跨站点时,任何情况都不发送Cookie; Lax: 限制稍微宽松,大多数情况下时不发送第三方Cookie的,除了a链接、预加载请求和GET表单; None: 关闭SameSite
属性,但必须同时设置Secure
属性,如下:
Set-Cookie: SameSite = None // 无效
Set-Cookie: SameSite = None; Secure // 有效
设置了Strict
或Lax
,基本就能阻止CSRF
攻击,前提是浏览器支持SameSite
属性。
总结
简单总结一下上文的CSRF攻击的防护策略:
- 自动防护策略:同源检测(
Origin
和Referer
验证); - 主动防护策略:
token
验证以及配合SameSite
设置; - 保护页面的幂等性,不要再GET请求中做用户操作。
为了更好的防御CSRF,最佳实践应该是结合上面总结的防御措施方式中的优缺点来综合考虑,结合当前Web应用程序自身的情况做合适的选择,才能更好的预防CSRF的发生。