什么是CSRF
跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。跟跨网站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。
CSRF攻击原理
CSRF是如何发起攻击的?下面以网银系统作为示例来说明CSRF的攻击原理。
1、受害者登录网银系统bank.com,并保留了登录凭证(Cookie);
2、攻击者诱导受害者访问黑客网站hacker.com;
3、黑客网站向网银系统发起转账请求,浏览器会默认携带网银系统bank.com的Cookie;
4、网银系统bank.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求;
5、网银系统以受害者的名义执行了转账操作。
至此,在用户不知情的情况下,网银执行了转账业务,这就是跨站(第三方站点的发起请求)请求伪造(非用户发起的请求)的基本攻击原理。
CSRF场景攻击类型
GET类型的CSRF
GET类型的CSRF利用非常简单,一般是利用img的图片设置为攻击链接:
<img src="http://bank.com/transfer?account=lisi&amount=100">
在受害者访问含有这个img的页面后,浏览器会自动向http://bank.com/transfer?account=lisi&amount=100发出一次HTTP请求。bank.com就会收到包含受害者登录信息的一次跨域请求。
POST类型的CSRF
这种类型的CSRF利用起来通常使用的是一个自动提交的表单,如:
<form action="http://bank.com/transfer">
<input type="hidden" name="account" value="zhangsan">
<input type="hidden" name="amount" value="100">
</form>
<script>
form[0].submit();
</script>
访问该页面后,表单会自动提交,相当于模拟用户完成了一次POST操作。
链接类型的CSRF
这种攻击方式主要是诱导用户进行点击,从而触发一次HTTP请求。
<a href="http://bank.com/transfer?account=lisi&amount=100">恭喜您中奖了,点击领奖</a>
防御措施
根据CSRF的特点,要想攻击成功发生,需要满足如下两个条件:
- 用户在被攻击网站完成了登录;
- 用户在第三方网站触发了被攻击网站的请求,而被攻击网站无法识别请求来源。
针对第一个条件:
- 对核心操作增加二次身份验证,防止自动在后台运行;
- 可以设置会话有限期,当用户离开网站较长时间,需要进行重新身份验证,可以减少被攻击的机率。
针对第二个条件,是技术层面重要的防范措施,防范措施如下:
- 语义一致性:严格区分GET、POST请求,操作类请求必须使用POST请求,这样可以减少防范范围。
-
阻止外域访问
- 同源检测:校验HTTP请求的Origin Header和Referer Header请求源信息,阻止外部域名的请求。当前方案依赖浏览器发送正确的Origin或Referer字段,各个浏览器的实现无法得到保证,同时也不能保证浏览器是否存在安全漏洞被攻击者利用,从而篡改Origin和Referer字段。并且虽然大多数CSRF都是跨域请求,但不排除个别网站存在其他漏洞被攻击者利用,实现本域攻击。
- Samesite Cookie:控制只有同域(子域)能访问Cookie。由于Samesite是Google提出来的,其他浏览器尚未普及,存在兼容性问题;而且当前方案会牺牲网站的易用性,只要是从其他域名跳转过来都需要重新登录。
-
随机数一致性检测
- CSRF Token:用户登录后,随机生成csrf_token,用户在做核心操作表单提交(POST)时必须携带csrf_token,并且在服务端校验csrf_token的合法性。CSRF Token是目前最成熟、使用最广泛的方法,其缺点是在分布式应用中,token的管理和实现需要一定的成本,不过目前分布式缓存技术已经相当普及,这也已经不算是啥缺点。
- 双重Cookie验证:利用CSRF攻击不能访问用户Cookie的特点,前端请求时,请求参数和Cookie同时携带csrf_token,服务端对一致性进行校验。当前方案节省了服务端token管理成本,服务端只需要针对前端提交上来的Cookie和请求参数中携带的token进行比对校验即可。但此方案存在一定的安全风险,如果任何一个子域下的页面存在XSS攻击,那么就可能导致Cookie被攻击者修改,从而导致防御失效。
以上描述的几种防御措施中,其中CSRF Token是目前最成熟、使用最广泛的方法,推荐使用CSRF Token来防御CSRF攻击。