一、CSRF简介
1、CSRF的全名是cross site request forgery,翻译成中文就是跨站点请求伪造。
2、CSRF区别于XSS在于它只发送请求,不会在目标域下执行JS。
3、举个栗子理解一下什么是CSRF~
攻击者首先在自己的域构造一个页面:
http://www.a.com/csrf.html
其内容为:
<img src="http://blog.sohu.com/manage/entry.do?m=delete&id=123">
使用了一个<img>标签,其地址指向了删除博客文章的连接。
攻击者诱使博客主访问这个页面,该用户看到一张无法显示的图片,其实背后这篇ID为123的文章已经被删除了。
原来刚才访问http://www.a.com/csrf.html时,图片标签向搜狐的服务器发送了一次get请求:导致文章删除。
回顾整个攻击过程,攻击者仅仅诱使用户访问了一个页面,就以该用户的身份在第三方站点执行了一次操作。
在这个栗子中,如果在火狐浏览器中演示是会成功的,但是如果在IE浏览器中是不会成功的,因为火狐浏览器默认允许发送第三方cookie。
二、CSRF进阶
浏览器所持有的cookie分为两种:一种是"session cookie",又称"临时cookie"(浏览器关了,cookie也就消失了;保存在浏览器进程的内存空间中);另一种是“Third-party Cookie”,也称为“本地Cookie”(时间到了就会关闭;保存在本地)。
如果浏览器从一个域的页面中,要加载另一个域的资源,由于安全原因,某些浏览器会阻止本地Cookie的发送。
IE出于安全原因,默认禁止了浏览器在<img>,<iframe>,<script>,<link>等标签中发送第三方cookie。
Firefox中,默认策略是允许发送第三方Cookie的。所以上面的例子中可以攻击成功。
而对于IE浏览器,攻击者则需要精心构造攻击环境,比如诱使用户在当前浏览器中先访问目标站点,使得Session Cookie有效,再实施CSRF攻击。
三、P3P头的副作用
P3P Header 是W3C制定的一项关于隐私的标准。
如果网站返回给浏览器的HTTP头中包含有P3P头,则在某种程度上来说,将允许浏览器发送第三方Cookie,即使在IE浏览器中也是可以的。
<?php
header("p3p:CP=CURa ADMa DEVa PSAo PSDo OUR BUS NUI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR");
header("set-Cookie:test=axis;expires=Sun,23-Dec-2018 08:13:02 GMT;domain=.a.com;path=/");
?>
P3P头的介入改变了浏览器的隐私策略,从而使得<iframe>,<script>等标签在IE中不再拦截第三方Cookie的发送。P3P头只需要由网站设置一次即可,
之后每次请求都会遵循此策略,而不需要再重复设置。
正因为P3P头目前在网站的应用中被广泛应用,因此在CSRF的防御中不能依赖于浏览器对第三方Cookie的拦截策略,不能心存侥幸。
很多时候,如果测试CSRF时发现<iframe>等标签在IE中居然能发送Cookie,而又找不到原因,那么很可能就是因为P3P头在作怪。
四、防御手段
1、验证码
网站不能给所有的操作都加上验证码,所以验证码只能作为防御CSRF的一种辅助手段。
2、referer check
在提交发帖时,Referer的值必然是发帖表单所在的页面。如果不是,那么极有可能是CSRF攻击。
通过检查Referer是否合法来判断用户是否被CSRF攻击,也仅仅是满足了防御的充分条件。
3、anti CSRF Token
现在业界一致的做法是使用一个Token。
CSRF为什么能够攻击成功?其本质原因是重要操作的所有参数都是可以被攻击者猜测到的。
攻击者只有预测出URL的所有参数与参数值,才能成功的构造一个伪造的请求,反之,失败。
例如:
http://host/path/delete?username=abc&item=123&token=[random(seed)]
token需要足够随机,还要保密。只能为用户与服务器所共同持有,不能被第三者知晓。在实际应用时,token可以放在用户的session中,或者浏览器的Cookie中。
由于token的存在,攻击者无法再构造出一个完整的URL实施CSRF攻击。token需要同时放在表单和session中。在提交请求时,服务器只需验证表单中的token,与用户session(或cookie)
中的token是否一致,如果一致,则认为是合法请求,反之。
在使用token时,应该尽量把Token放在表单中。把敏感操作由GET改成POST,以form表单(或AJAX)的形式提交,可以避免Token泄露。