CSRF: 不要低估了我的危害和攻击能力

作者:iceskysl
来源:IceskYsl@1sters!

CSRF这种攻击方式虽然提出来很久(在2006年的时候就有了)了,但是这个沉睡的攻击巨人直到前不久才逐渐走入我们的视线,到底CSRF是啥,危害到底有多大?常见的利用方式是如何的,今天作为“安全相关 | Security”分类的第一篇文章,我按照自己的理解告诉你,不要低估了CSRF危害性和攻击能力。

一、什么是CSRF
先看看CSRF的原文说明,如下:

Cross Site Reference Forgery works by including malicious code or a link in a page that accesses a web application that the user is believed to have authenticated. If the session for that web application has not timed out, an attacker may execute unauthorized commands.


二、CSRF案例说明和分析
自然,这里拿Rails程序来举例子说明这些问题,大家知道Rails2之前是把session放在服务器端(文件或者DB或者缓存中),客户但在 cookie中保存sessionid;而到了Rails2后,还有一种方式是把session放在基于cookie的客户端中。当然这两样都各有道理, 各有优劣,不在我们这次说的范围之内。我们继续说,当我们向一个域名发送一个请求的时候,如果本店存在这个域名的cookie,浏览器会自动的把 cookie附带上。这样本来没有啥问题,也是我们为了解决http无状态记录的解决方案,但是有个问题出现了,如果出现一个到其他域名的请求,浏览区在 加载的时候,也把cookie给带上了,会有什么问题?我们举个简单的也很常见的例子来说明这个问题。
—————————–案例——————————
1、Bob在自己的电脑上刚刚查看完自己的银行A账户余额,然后比较无聊就跑到一个公开的BBS上灌水,当他看到一篇“银行A的内部照片”的帖子,很有兴趣的打开这个帖子想看看自己信任的银行A的内部图片是啥样子的,殊不知,这其实是一个attacker精心设计的骗局。
2、在这个帖子中确实有几个图片,看上去真的像是银行A的照片,但是其中有个图片没显示出来,Bob以为是自己网速太慢,导致这个图片没有加载进来,也没在意。只是对这些并不是十分满意的照片摇摇头,就关了这个帖子。
3、几天后,Bob猛然发现自己在银行A的账户上少了1000元,到底是怎么了?

分析:
为什么钱少了呢?我们得分析一下上面这个案例,好记得当时Bob说有个图片没显示么,是的,我们来看看这个图片的地址,惊奇的发现是:,这是一个什么地址?聪明的您一定很快就能明白,这个地址是邪恶的,看上去,他的意思是打开这个地址的人,给attacker转了1000元。
这怎么可能?你肯定急了,我怎么能随便给一个人转1000元呢,而且我都不知道呀!但是,注意了,这其实是完全有可能的。还记得当时Bob刚刚查看完整及的帐号信息,基于银行A的cookie并不过期,当出现如上链接出现在src的时候(note that .src is meant to be src),浏览器尝试着按照本地的cookie去加载上面这个URL,而银行A验证了来源请求的cookie是可以的,所以就这样事情就悄悄的发生了。
——————————-案例结束—————————

ok,看明白了么,这就是CSRF,一句话给他下个定义就是:借你的cookie在你不知道的时候悄悄的做了一些你不愿意做 的事情。恶日期这里有个更要命的是,这个包含上述URL的图片或者链接,并不需要一定是放在银行A的服务器上,相反可以在任一地方,比如blog,公开的 BBS,或者一些群发的Mail中等等,如此多的场合下,这些都有可能存在陷阱。
再看一副图片吧,其说明的正是CSRF的攻击原理。

三、CSRF的预防
看上去很恐怖吧,是的,确实恐怖,意识到恐怖是个好事情,这样会促使你接着往下看如何改进和防止类似的漏洞出现。
总体来说,预防CSRF主要从2个方面入手,分别是:
1、正确使用GET,POST和Cookie;
2、在non-GET请求中使用Security token;

一般上,大家知道的浏览器发送请求的方式有GET或者POST,但是还有一种比较常用的是Cookie,至于其他的HTTP协议请求方式,你可以google,一般按照W3C的规范:
1、GET常用在查看,列举,展示的时候;
2、POST常用在下达订单,改变一个资源的属性或者做其他一些事情;

ok,我们这里拿Rails按照前面列举的2种预防手段做说明,首先,我们可以在Rails的控制权中(controller)将一些方法(action)限定(verify)为只能使用POST或者GET,例如:
Ruby代码

verify :method => :post, :only => [ :transfer ], :redirect_to => { :action => :list }

恩,很好,这样做下限制以后,前面案例中的方法就失效了,因为这里我们限定了transfer必须使用POST来提交请求,当GET请求来的时候并不会被响应。
万事大吉了?NO!因为POST的请求也是可以被构造出来后自动发送的,如何实现,看下面吧,你肯定会吃惊的。
XML/HTML代码

<a .href="http://www.1sters.com/" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = 'http://www.example.com/account/destroy'; f.submit();return false;">点我试试</a>

是的,这就是一个活生生的例子(.href is meant to be href),使用link的href或者img的src都可以的,再想想一个Attacher放了一个图片,然后写了一个onmouseover方法,执行上述的那段JS,如下,或者使用AJAX。
XML/HTML代码

<img .src="http://www.harmless.com/img" width="400" height="400" onmouseover="…" />

所以,限定为POST后还不是非常的保险,怎么办?不急,我们还有第二步,给non-GET的请求设置 security token,如何实现,在Rails2以后非常简单(也是默认的),我们只需要在environment.rb中添加如下代码:
Ruby代码

config.action_controller.session = { 
	 :session_key => '_csrf_session', 
	 :secret => 'ae4b43dda38ff78bb50898b2935da76d1e224061ab72a9399d34cea4c6178eee6dae815fff920a20642f27abda83b793da4e9b6cf20c4838805e80abf53e318a' 
	}

然后在application controller中包含如下security token设置:
Ruby代码

protect_from_forgery :secret => '053cef294a333f72c3584311799c69d2'

ok,基本上安全了,如果这时POST请求过去,但是security token和session计算出来的secret和服务端的secret匹配不上的话,就会返回一个ActionController::InvalidAuthenticityToken错误,防止该类缺陷的出现。
安全了,也许你要说,那我如果能破解出protect_from_forgery,不进OK了么,按照理论上是,但是实际是破解是基本上不可能的,因为有人曾计算过,暴力破解该串大概需要2的11次方时间,后续我将再写一篇文章详细的介绍,这里不再赘述。

四、总结
总的来说,CSRF的兴起刚刚开始,网络上肯定会有一股热潮,Railser们一定要注意自己的程序的安全性,CSRF比你我能想到的更有威胁,千万别小瞧了它。

相关日志

楼被抢了 7 层了... 抢座Rss 2.0或者 Trackback

  • Neeao

    来占个座,真恶心,用饭否,^_^。你一发我就知道,晕倒。

  • 鬼仔

    日你下先。
    饭否的那个是自动的,url也都用的tinyurl

  • firefox

    很不错 感谢分享!

  • phthegreat

    传说中的跨站?

  • www

    一个验证码是不是能解决问题?

  • 极度*病毒

    鬼哥,我在几个人的blog上看到这篇文章,到底谁写的?
    来源:IceskYsl@1sters! 什么人?这么神秘?

  • 鬼仔

    呵呵,作者叫iceskysl,搜一下就知道了。

发表评论