CSRF跨站点请求伪造

全名:Cross Site Request Forgery, 翻译成中文就是跨站点请求伪造
它是一种常见的web攻击,但很多开发者对它很陌生。CSRF也是web安全中最容易被忽略的一种攻击方式。
CSRF攻击者在用户已经登录目标网站之后,诱使用户访问一个攻击页面,利用目标网站对用户的信任,以用户身份在攻击页面对目标网站发起伪造用户操作的请求,达到攻击目的。
http://blog.sohu.com/manage/entry.do?m=delete&id=12345
这个url同时还存在CSRF漏洞,我们将尝试利用csrf漏洞,删除编号为12345的博客文章,这篇文章的标题是”test1″
攻击者首先在自己的域构造一个页面:
www.a.com/csrf.html
其内容为:
<img src=”http://blog.sohu.com/manage/entry.do?m=delete&id=12345″>
使用一个img标签,其地址指向删除博客文章的链接。
访问了这个页面,博客文章就被删了。
回顾整个攻击过程,攻击者仅仅诱使用户访问了一个页面,就以该用户身份在第三方站点里执行了一次操作,试想,如果这张图片是展示在某个论坛,某个博客,甚至搜狐的一些用户空间中,会产生什么效果呢?只需要经过精心的设计, 就能够起到更大的破坏作用。
这个删除博客文章的请求,是攻击者所伪造的,所以这种攻击就叫做“跨站点请求伪造”

CSRF的防御:
a. 验证码
    验证码被认为是对抗csrf攻击最简洁而有效的防御方法。
    csrf 攻击的时候,往入是在用户不知情的情况下构造了网络请求,而验证码,则强制用户必须与应用进行交互,才能完成最终请求。
b.Referer check
    常见的互联网应用,页面与页面之间都具有一定的逻辑关系,这就使得每个正常请求的Referer具有一定的规律。
    即使我们能够通过检查Referer是否合法来判断用户是否被CSRF攻击,也仅仅是满足了防御的充分条件
    Referer check的缺陷在于:服务器并非什么时候都能取到Referer。很多用户出于隐私保护的考虑,限制了Referer的发送。
c. Anti CSRF token       
 CSRF的本质是:所有参数都是可以被攻击者猜测到的。
    出于这个原因,可以想到一个解决方案:把参数加密,或者使用一些随机数,从而让攻击者无法猜测到参数值。这是“不可预测性原则”的一种应用。

举例:
简单版
假如博客园有个加关注的GET接口,blogUserGuid参数很明显是关注人Id, 如下:
http://www.cnblogs.com/mvc/Follow/FollowBlogger.aspx?blogUserGuid=4e8c33d0-77fe-df11-ac81-842b2b196315
那我只需要在我的一篇博文内容里写一个img标签:
<img style=”width:0;” src=”http://www.cnblogs.com/mvc/Follow/FollowBlogger.aspx?blogUserGuid=4e8c33d0-77fe-df11-ac81-842b2b196315″   />
那么只要有人打开我这篇博文,那不会自动关注我。

升级版:
假如博客园还是有个加关注的接口,不过已经限制了只获取POST请求的数据。这个时候就做一个第三方的页面,但里面包含form提交代码,然后通过QQ,,邮箱等社交工具传播,诱惑用户去打开,那打开博客园的用户就中招了。

<!DOCTYPE HTML>
<html lang=”en-US”>
<head><title>CSRF SHOW</title></head>     
<body>          
<!–不嵌iframe会跳转–>          
<iframe style=”display:none;”>
                <form  name=”form1″ action=”http://www.cnblogs.com/mvc/Follow/FollowBlogger.aspx” method=”post”>                    
<input type=”hidden” name=”blogUserGuid” value=”4e8c33d0-77fe-df11-ac81-842b2b196315″/>                    
<input type=”submit” value>               
</form>               

<script>
document.forms.form1.submit();
</script>          
</iframe>     
</body>
</html>

进阶版:
假如博客园还是有个加关注的接口,已经限制POST,但博文内容是直接贴进HTML(未过滤),那就遭受XSS攻击。那么就可以直接把上面代码嵌入博文,那么只要有人打开我这篇博文,还是会自动关注我,这组合攻击方式称为XSRF。
本质原因:
CSRF攻击是源于Web的隐式身份验证机制!Web的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的。CSRF攻击的一般是由服务端解决。

防御手段:
1. 尽量使用POST,限制GET
2. 浏览器Cookie策略
3. 加验证码
验证码,强制用户必须与应用进行交互,才能完成最终请求。在通常情况下,验证码能很好遏制CSRF攻击。但是出于用户体验考虑,网站不能给所有的操作都加上验证码。因此验证码只能作为一种辅助手段,不能作为主要解决方案。
4. Referer Check
Referer Check在Web最常见的应用就是“防止图片盗链”。同理,Referer Check也可以被用于检查请求是否来自合法的“源”(Referer值是否是指定页面,或者网站的域),如果都不是,那么就极可能是CSRF攻击。
但是因为服务器并不是什么时候都能取到Referer,所以也无法作为CSRF防御的主要手段。但是用Referer Check来监控CSRF攻击的发生,倒是一种可行的方法。
5. Anti CSRF Token
现在业界对CSRF的防御,一致的做法是使用一个Token(Anti CSRF Token)。
例子:
1. 用户访问某个表单页面。
2. 服务端生成一个Token,放在用户的Session中,或者浏览器的Cookie中。
3. 在页面表单附带上Token参数。
4. 用户提交请求后, 服务端验证表单中的Token是否与用户Session(或Cookies)中的Token一致,一致为合法请求,不是则非法请求。这个Token的值必须是随机的,不可预测的。由于Token的存在,攻击者无法再构造一个带有合法Token的请求实施CSRF攻击。另外使用Token时应注意Token的保密性,尽量把敏感操作由GET改为POST,以form或AJAX形式提交,避免Token泄露。
CSRF的Token仅仅用于对抗CSRF攻击。当网站同时存在XSS漏洞时候,那这个方案也是空谈。所以XSS带来的问题,应该使用XSS的防御方案予以解决。