web安全之token和CSRF攻击

Posted 葡萄干是个程序员

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了web安全之token和CSRF攻击相关的知识,希望对你有一定的参考价值。

       上文我转载了两篇关于Thinkphp令牌验证的文章(ThinkPHP中的create方法与自动令牌验证)。其中提及到了  token ,这里针对 token 的作用,转载了另外两篇文章。

web安全之token   Web安全之CSRF攻击

web安全之token

参考:http://blog.csdn.net/sum_rain/article/details/37085771 

Token,就是令牌,最大的特点就是随机性,不可预测。一般黑客或软件无法猜测出来。 

那么,Token有什么作用?又是什么原理呢? 

Token一般用在两个地方: 

1)防止表单重复提交、 2)anti csrf攻击(跨站点请求伪造)。 

两者在原理上都是通过session token来实现的。当客户端请求页面时,服务器会生成一个随机数Token,并且将Token放置到session当中,然后将Token发给客户端(一般通过构造hidden表单)。下次客户端提交请求时,Token会随着表单一起提交到服务器端。 
然后,如果应用于"anti csrf攻击",则服务器端会对Token值进行验证,判断是否和session中的Token值相等,若相等,则可以证明请求有效,不是伪造的。 
不过,如果应用于"防止表单重复提交",服务器端第一次验证相同过后,会将session中的Token值更新下,若用户重复提交,第二次的验证判断将失败,因为用户提交的表单中的Token没变,但服务器端session中Token已经改变了。 

上面的session应用相对安全,但也叫繁琐,同时当多页面多请求时,必须采用多Token同时生成的方法,这样占用更多资源,执行效率会降低。因此,也可用cookie存储验证信息的方法来代替session Token。比如,应对"重复提交"时,当第一次提交后便把已经提交的信息写到cookie中,当第二次提交时,由于cookie已经有提交记录,因此第二次提交会失败。 
不过,cookie存储有个致命弱点,如果cookie被劫持(xss攻击很容易得到用户cookie),那么又一次gameover。黑客将直接实现csrf攻击。 

所以,安全和高效相对的。具体问题具体对待吧。 

此外,要避免"加token但不进行校验"的情况,在session中增加了token,但服务端没有对token进行验证,根本起不到防范的作用。 

还需注意的是,对数据库有改动的增删改操作,需要加token验证,对于查询操作,一定不要加token,防止攻击者通过查询操作获取token进行csrf攻击。但并不是这样攻击者就无法获得token,只是增大攻击成本而已。 



Web安全之CSRF攻击


CSRF是什么? 

CSRF(Cross Site Request Forgery),中文是跨站点请求伪造。CSRF攻击者在用户已经登录目标网站之后,诱使用户访问一个攻击页面,利用目标网站对用户的信任,以用户身份在攻击页面对目标网站发起伪造用户操作的请求,达到攻击目的。 

举个例子  简单版: 

假如博客园有个加关注的GET接口,blogUserGuid参数很明显是关注人Id,如下: 

那我只需要在我的一篇博文内容里面写一个img标签: 

那么只要有人打开我这篇博文,那就会自动关注我。 

升级版: 

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

在说例子之前要纠正一个iframe问题,有人会直接在第三方页面这样写。如下: 

<!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> 

这样是用问题的,由于同源策略的原因,iframe内容根本加载不出来,所以里面form提交当然不会执行。 

PS:我尝试了chrome、IE11、Firefox,情况都是这样。 

所以可以用嵌多一层页面方式解决,如下: 

第一个展示页面(test): 

<!DOCTYPE HTML> 
<html lang="en-US"> 
<head> 
<title>CSRF SHOW</title> 
</head> 
<body> 
<iframe style="display:none;" src="test2.html"></iframe> 
</body> 
</html> 

第二个隐藏页面(test2): 

<!DOCTYPE HTML> 
<html lang="en-US"> 
<head> 
<title>CSRF GET</title> 
<body> 
<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>  </body>  </html> 

这样就可以解决了,有人会问为什么要加多一层iframe,因为不嵌iframe页面会重定向,这样就降低了攻击的隐蔽性。另外我们test页面不使用XMLHTTPRequest发送POST请求,是因为有跨域的问题,而form可以跨域post数据。 

进阶版: 

假如博客园还是有个加关注的接口,已经限制POST,但博文内容是直接贴进HTML(未过滤),那就遭受XSS攻击。那么就可以直接把上面代码嵌入博文,那么只要有人打开我这篇博文,还是会自动关注我,这组合攻击方式称为XSRF。 

CSRF攻击的本质原因 

CSRF攻击是源于Web的隐式身份验证机制!Web的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的。CSRF攻击的一般是由服务端解决。 

CSRF工具的防御手段 

1. 尽量使用POST,限制GET 

GET接口太容易被拿来做CSRF攻击,看第一个示例就知道,只要构造一个img标签,而img标签又是不能过滤的数据。接口最好限制为POST使用,GET则无效,降低攻击风险。 

当然POST并不是万无一失,攻击者只要构造一个form就可以,但需要在第三方页面做,这样就增加暴露的可能性。 

2. 浏览器Cookie策略 

IE6、7、8、Safari会默认拦截第三方本地Cookie(Third-party Cookie)的发送。但是Firefox2、3、Opera、Chrome、android等不会拦截,所以通过浏览器Cookie策略来防御CSRF攻击不靠谱,只能说是降低了风险。 

PS:Cookie分为两种,Session Cookie(在浏览器关闭后,就会失效,保存到内存里),Third-party Cookie(即只有到了Exprie时间后才会失效的Cookie,这种Cookie会保存到本地)。 

PS:另外如果网站返回HTTP头包含P3P Header,那么将允许浏览器发送第三方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的防御方案予以解决。 

总结 

CSRF攻击是攻击者利用用户的身份操作用户帐户的一种攻击方式,通常使用Anti CSRF Token来防御CSRF攻击,同时要注意Token的保密性和随机性。 

参考文献: 

1. 《浅谈CSRF攻击方式》 

2. 《白帽子讲Web安全》 

本文为原创文章,转载请保留原出处,方便溯源,如有错误地方,谢谢指正。 

本文地址:http://www.cnblogs.com/lovesong/p/5233195.html




以上是关于web安全之token和CSRF攻击的主要内容,如果未能解决你的问题,请参考以下文章

Web安全之跨站请求伪造漏洞

Web安全之CSRF攻击

Web安全之CSRF攻击

php web开发安全之csrf攻击的简单演示和防范

web安全之CSRF(跨站域请求伪造)攻击详解应对和测试

web安全值csrf