跨站点请求伪造 - CSRF
1、CSRF简介
CSRF的全名是Cross Site Request Forgery,翻译成中文就是跨站点请求伪造。可以这么理解:攻击者盗用了你的身份,以你的名义发送恶意请求。
2、CSRF进阶
2.1、浏览器的Cookie策略
浏览器所持有的Cookie分为两种:一种是 “ Session Cookie ”,又称 “ 临时Cookie ”;另一种是 “ Third-party Cookie ”,也称为 “ 本地Cookie ”。
两者的区别在于,“ 本地Cookie ”是服务器在Set-Cookie时制定了Expire时间,只有到了Expire时间后Cookie才会失效,所以这种Cookie会保存在本地;而 “ Session Cookie ”则没有指定Expire时间,所以浏览器关闭后,Session Cookie就失效了。
如果浏览器从一个域的页面中,要加载另一个域的资源,由于安全原因,某些浏览器会阻止Third-party Cookie的发送。
有一个页面http://www.b.com/csrf-test.html,此页面构造了CSRF以访问www.a.com。
<iframe src="http://www.a.com"></iframe>
这时就会发现,只能发送出Session Cookie,而Third-party Cookie被禁止了。
这是因为IE出于安全考虑,默认禁止了浏览器在< img>、< iframe>、< script>、< link>等标签中发送第三方Cookie。
在当前浏览器中,默认会拦截Third-party Cookie的有:IE 、Safari;不会拦截的有:Firefox、Opera、Chrome、Android等。
2.2、P3P头的副作用
P3P Header是W3C制定的一项关于隐私的标准,全称是The Platform for Privacy Preferences。
如果网站返回给浏览器的HTTP头中包含有P3P头,则在某种程度上来说,将允许浏览器发送第三方Cookie。在IE下即使是< iframe>、< script>等标签也将不再拦截第三方Cookie的发送。
很多时候,如果测试CSRF时发现< iframe>等标签在IE中居然能发送Cookie,而又找不到原因,那么很可能就是因为P3P头在作怪。
2.3、Flash CSRF
flash功能丰富,当然也有向任意站点发送请求的API,我们可以利用flash而不是js来控制浏览器向目标URL发送请求,这就实现CSRF了。比如flash8中的loadVariables,flash9中的sendToURL都是可以实现这个功能的。
编译好之后执行,你会发现它向百度POST数据,如果你的浏览器中有baidu.com的Cookie,Cookie也会发送出去的,这里就可以绕过IE的隐私安全限制。(如果直接img或者iframe向baidu.com发送数据,cookie是会被阻拦的)
3、CSRF防御
3.1、验证码
验证码被认为是对抗CSRF攻击最简介而有效的防御方法。 但是验证码并非万能的,很多时候,出于用户体验考虑,网站不能给所有的操作都加上验证码。因此,验证码只能作为防御CSRF的一种辅助手段。
3.2、Referer Check
Referer 是HTTP请求header的一部分,当浏览器向web服务器发送请求的时候,头信息里有包含Referer。Referer信息告诉服务器该网页是从哪个页面链接过来的,服务器因此可以获得一些信息用户处理。
虽然Referer可以用来判断用户是否被CSRF攻击,但是服务器并非什么时候都可以取到Referer。很多用户出于隐私保护的考虑,限制了Referer的发送。在某些情况下,浏览器也不会发送Referer,比如从HTTPS跳转到HTTP,出于安全的考虑,浏览器也不会发送Referer。
3.3、Anti CSRF Token
现在业界针对CSRF的防御,一致的做法是使用一个Token。
3.3.1、CSRF的本质
CSRF为什么能够攻击成功?其本质原因是重要操作的所有参数都是可以被攻击者猜测到的。
攻击者只有预测出URL的所有参数和参数值,才能成功构造一个伪造的请求,才能攻击成功。反之,将失败。
因此,我们可以把参数加密,或者使用一些随机数,从而让攻击者无法猜测到参数值。
我们在URL中添加一个参数Token。这个Token的值是随机的,不可预测的。如下:
http://host/path/delete?user=abc&item=123&token=[random(seed)]
Token应该作为一个秘密,为服务器和用户所共同持有。在实际应用中,Token可以放在用户的Session中,或者浏览器的Cookie中。
Token需要同时放在表单和Session中。在提交请求时,服务器只需验证表单中的Token,与用户Session(或Cookie)中的Token是否一致。如果不一致,则可能发生了CSRF攻击。
3.3.1、Token使用原则
Token的目的不是为了防止重复提交。所以为了使用方便,可以允许在一个用户的有效生命周期内,在Token消耗掉前都使用同一个Token。但是如果用户已经提交了表单,则这个Token已经消耗掉,应该再次重新生成一个新的Token。
在使用Token的时候,应该尽量把Token放在表单中。把敏感操作由GET改为POST,以form表单(或者AJAX)的形式提交,可以避免Token泄露。