购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

4.2 CSRF进阶

4.2.1 浏览器的Cookie策略

在上节提到的例子里,攻击者伪造的请求之所以能够被搜狐服务器验证通过,是因为用户的浏览器成功发送了Cookie的缘故。

浏览器所持有的Cookie分为两种:一种是“Session Cookie”,又称“临时Cookie”;另一种是“Third-party Cookie”,也称为“本地Cookie”。

两者的区别在于,Third-party Cookie是服务器在Set-Cookie时指定了Expire时间,只有到了Expire时间后Cookie才会失效,所以这种Cookie会保存在本地;而Session Cookie则没有指定Expire时间,所以浏览器关闭后,Session Cookie就失效了。

在浏览网站的过程中,若是一个网站设置了Session C ookie,那么在浏览器进程的生命周期内,即使浏览器新打开了Tab页,Session Cookie也都是有效的。Session Cookie保存在浏览器进程的内存空间中;而Third-party Cookie则保存在本地。

如果浏览器从一个域的页面中,要加载另一个域的资源,由于安全原因,某些浏览器会阻止Third-party Cookie的发送。

下面这个例子,演示了这一过程。

在 http://www.a.com/cookie.php 中,会给浏览器写入两个Cookie:一个为Session Cookie,另一个为Third-party Cookie。访问这个页面,发现浏览器同时接收了这两个Cookie。

浏览器接收Cookie

这时再打开一个新的浏览器Tab页,访问同一个域中的不同页面。因为新Tab页在同一个浏览器进程中,因此Session Cookie将被发送。

Session Cookie被发送

此时在另外一个域中,有一个页面 http://www.b.com/csrf-test.html,此页面构造了CSRF以访问 www.a.com。

这时却会发现,只能发送出Session Cookie,而Third-party Cookie被禁止了。

只发送了Session Cookie

这是因为IE出于安全考虑,默认禁止了浏览器在<img>、<iframe>、<script>、<link>等标签中发送第三方Cookie。

再回过头来看看Firefox的行为。在Firefox中,默认策略是允许发送第三方Cookie的。

在Firefox中允许发送第三方Cookie

由此可见,在本章一开始所举的CSRF攻击案例中,因为用户的浏览器是Firefox,所以能够成功发送用于认证的Third-party Cookie,最终导致CSRF攻击成功。

而对于IE浏览器,攻击者则需要精心构造攻击环境,比如诱使用户在当前浏览器中先访问目标站点,使得Session Cookie有效,再实施CSRF攻击。

在当前的主流浏览器中,默认会拦截Third-party Cookie的有:IE 6、IE 7、IE 8、Safari;不会拦截的有:Firefox 2、Firefox 3、Opera、Google Chrome、Android等。

但若CSRF攻击的目标并不需要使用Cookie,则也不必顾虑浏览器的Cookie策略了。

4.2.2 P3P头的副作用

尽管有些CSRF攻击实施起来不需要认证,不需要发送Cookie,但是不可否认的是,大部分敏感或重要的操作是躲藏在认证之后的。因此浏览器拦截第三方Cookie的发送,在某种程度上来说降低了CSRF攻击的威力。可是这一情况在“P3P头”介入后变得复杂起来。

P3P Heade r是W3C制定的一项关于隐私的标准,全称是The Platform for Pri vacy Preferences。

如果网站返回给浏览器的HTTP头中包含有P3P头,则在某种程度上来说,将允许浏览器发送第三方Cookie。在IE下即使是<iframe>、<script>等标签也将不再拦截第三方Cookie的发送。

在网站的业务中,P3P头主要用于类似广告等需要跨域访问的页面。但是很遗憾的是,P3P头设置后,对于Cookie的影响将扩大到整个域中的所有页面,因为Cookie是以域和path为单位的,这并不符合“最小权限”原则。

假设有www.a.com与 ww w.b.com两个域,在www.b.com上有一个页面,其中包含一个指向 www.a.com 的iframe。

http://www.b.com/test.html 的内容为:

http://www.a.com/test.php 是一个对 a.com 域设置 C ookie的页面,其内容为:

当请求http://www.b.com/test.html时,它的iframe会告诉浏览器去跨域请求www.a.com/test.php。test.php会尝试 Set-Cookie,所以浏览器会收到一个Cookie。

如果 Set-Cook ie 成功,再次请求该页面,浏览器应该会发送刚才收到的Cookie。可是由于跨域限制,在a.com上Set-Cookie是不会成功的,所以无法发送刚才收到的Cookie。 这里无论是临时Cookie还是本地Cookie都一样。

测试环境请求过程

可以看到,第二次发包,只是再次接收到了Cookie,上次Set-Cookie的值并不曾发送,说明没有Set-Cookie成功。但是这种情况在加入了P3P头后会有所改变,P3P头允许跨域访问隐私数据,从而可以跨域Set-Cookie成功。

修改 www.a.com/test.php如下:

再次重复上面的测试过程:

测试环境请求过程

可以看到,第二个包成功发送出之前收到的Cookie。

P3P头的介入改变了a.com的隐私策略,从而使得<iframe>、<script>等标签在IE中不再拦截第三方Cookie的发送。P3P头只需要由网站设置一次即可,之后每次请求都会遵循此策略,而不需要再重复设置。

P3P的策略看起来似乎很难懂,但其实语法很简单,都是一一对应的关系,可以查询W3C标准。比如:

CP 是 C ompact Policy 的简写;CURa 中 CUR 是 <cu rrent/> 的简写;a 是 always 的简写。如下表:

此外,P3P头也可以直接引用一个 XM L 策略文件:

若想了解更多的关于P3P头的信息,可以参考W3C标准

正因为P3P头目前在网站的应用中被广泛应用,因此在CSRF的防御中不能依赖于浏览器对第三方Cookie的拦截策略,不能心存侥幸。

很多时候,如果测试CSRF时发现<iframe>等标签在IE中居然能发送Cookie,而又找不到原因,那么很可能就是因为P3P头在作怪。

4.2.3 GET? POST?

在CSRF攻击流行之初,曾经有一种错误的观点,认为CSRF攻击只能由GET请求发起。因此很多开发者都认为只要把重要的操作改成只允许POST请求,就能防止CSRF攻击。

这种错误的观点形成的原因主要在于,大多数CSRF攻击发起时,使用的HTML标签都是<img>、<iframe>、<script>等带“src”属性的标签,这类标签只能够发起一次GET请求,而不能发起POST请求。而对于很多网站的应用来说,一些重要操作并未严格地区分GET与POST,攻击者可以使用GET来请求表单的提交地址。比如在PHP中,如果使用的是$_REQUEST,而非 $_POST 获取变量,则会存在这个问题。

对于一个表单来说,用户往往也就可以使用GET方式提交参数。比如以下表单:

用户可以尝试构造一个GET请求:

来提交,若服务器端未对请求方法进行限制,则这个请求会通过。

如果服务器端已经区分了GET与POST,那么攻击者有什么方法呢?对于攻击者来说,有若干种方法可以构造出一个POST请求。

最简单的方法,就是在一个页面中构造好一个form表单,然后使用JavaScript自动提交这个表单。比如,攻击者在www.b.com/test.html中编写如下代码:

攻击者甚至可以将这个页面隐藏在一个不可见的iframe窗口中,那么整个自动提交表单的过程,对于用户来说也是不可见的。

在2007年的Gmail CSRF漏洞攻击过程中,安全研究者pdp展示了这一技巧。

首先,用户需要登录Gmail账户,以便让浏览器获得Gmail的临时Cookie。

用户登录Gmail

然后,攻击者诱使用户访问一个恶意页面。

攻击者诱使用户访问恶意页面

在这个恶意页面中,隐藏了一个iframe,iframe的地址指向pdp写的CSRF构造页面。

这个链接的实际作用就是把参数生成一个POST的表单,并自动提交。

由于浏览器中已经存在Gmail的临时Cookie,所以用户在iframe中对Gmail发起的这次请求会成功——邮箱的Filter中会新创建一条规则,将所有带附件的邮件都转发到攻击者的邮箱中。

恶意站点通过CSRF在用户的Gmail中建立一条规则

Google在不久后即修补了这个漏洞。

4.2.4 Flash CSRF

Flash也有多种方式能够发起网络请求,包括POST。比如下面这段代码:

除了URLRequest外,在Flash中还可以使用getURL,loadVars等方式发起请求。比如:

在IE 6、IE 7中,Flash发送的网络请求均可以带上本地Cookie;但是从IE 8起,Flash发起的网络请求已经不再发送本地Cookie了。

4.2.5 CSRF Worm

2008年9月,国内的安全组织80sec公布了一个百度的CSRF Worm。漏洞出现在百度用户中心的发送短消息功能中:

只需要修改参数sn,即可对指定的用户发送短消息。而百度的另外一个接口则能查询出某个用户的所有好友:

将两者结合起来,可以组成一个CSRF Worm——让一个百度用户查看恶意页面后,将给他的所有好友发送一条短消息,然后这条短消息中又包含一张图片,其地址再次指向CSRF页面,使得这些好友再次将消息发给他们的好友,这个Worm因此得以传播。

Step 1:模拟服务器端取得request的参数。

定义蠕虫页面服务器地址,取得?和&符号后的字符串,从URL中提取感染蠕虫的用户名和感染者的好友用户名。

Step 2:好友json数据的动态获取。

通过CSRF漏洞从远程加载受害者的好友json数据,根据该接口的json数据格式,提取好友数据为蠕虫的传播流程做准备。

Step 3:感染信息输出和消息发送的核心部分。

将感染者的用户名和需要传播的好友用户名放到蠕虫链接内,然后输出短消息。

这个蠕虫很好地展示了CSRF的破坏性——即使没有XSS漏洞,仅仅依靠CSRF,也是能够发起大规模蠕虫攻击的。 FcoxkQUlL8MpMMqJ6kVo6USNXqS157LYhkPuztHYPQAKt0LgRYBqwTyiMxneCIkA

点击中间区域
呼出菜单
上一章
目录
下一章
×