闲暇之余,加上某一些正在内测的站点准备运行之际,稍微就动了心思又对网络应用的安全性问题自行探究了一下。这次发现的是一种可以说是边际于漏洞又不是漏洞的东西:基于CSRF的降权拒绝服务攻击。
一般来说现在网络上的诸多漏洞都是采用升权(借用用户权限)进行的攻击。最常见的就是插入脚本的XSS攻击。由于脚本运行在用户相同的安全性标准下,这种漏洞经常会引发负面的越权问题。同理,CSRF漏洞多数也是采用升权进行的攻击,于是不断被忽视的就是CSRF降权拒绝服务攻击(名字是原创的,你未必找得到)。
一、什么是CSRF漏洞
CSRF是Cross Site Request Forgery(跨站点请求伪造)的缩写。这种攻击不同于XSS脚本注入攻击的最大区别是,攻击利用了浏览器对资源的载入来诱导浏览器发出能改变状态的请求。我们举一个例子:
某一个虚拟社区对用户进行积分转账是靠如下的访问:http://foo.com/bar/?action=transfer&to=205&amount=33
其中在请求的GET参数中,to是积分转账的授予用户,而amount则是转账的数目。在已经登录的系统下,程序将会授权用户的这次操作。而作为攻击者,由于无法在对方帐号的权限下访问网址,理论上也是无法进行转账的。
但是事实并非那么简单。浏览器在访问网页时,会自主下载一些资源,比如:图片、音乐、样式表、脚本文件。这些文件的下载(准确些说,是这些请求的发出)经常并没有用户独特的许可,但是却带着用户的权限进行。很显然,我们不能询问用户每一个资源的下载是否许可,但是大部分情况下,浏览器也不会胡乱请求资源。CSRF攻击正是利用了站点对用户浏览器的这种信任而得以实现的。
假定刚才的社区里,有一位用户引用了一张图片:<img src="http://foo.com/bar/?action=transfer&to=205&amount=100" />
浏览器在载入页面的同时,也将发出请求载入这张图片作为辅助资源。就这样,浏览器作为中间人代替了用户发出了这个请求,也就实现了浏览器的“升权”(自行代表了用户的权限)。凡是访问到包含这个图片的页面,已登录用户的浏览器将会带着一套已经认证的权限来执行操作。于是便在用户未主动参与的情况下发出了一个并不应该发出的请求,也就会导致100个积分被转到UID=205的账户。
二、CSRF的杜绝和被忽视的降权拒绝服务
虽然说刚才那一段听起来很危险,但是实际上不会出现这样的漏洞了,因为大部分的应用已经考虑到了并阻断了CSRF的功效发挥。其实阻断CSRF非常简单。CSRF的成功发动需要两个条件:1)你能诱导浏览器发出此类请求 2)请求不能因人而异。
这样一说,就发现有两个非常简单的解决方法。对于第一条,可以通过把请求由GET变为POST进行解决(浏览器不会自主发出POST请求的)。而对于第二条,很多站点则采用了NONCE(一次性校验数字)来进行的防御。此方法是,在生成连接时加入一个传递NONCE的字段。生成一个数字,保存在服务器上,同时也加到链接里面。当访问链接时,程序对比两个校验数字是否一致,然后再进行下一步操作。URL由 http://foo.com/bar/?action=transfer&amount=100&to=205 变为了http://foo.com/bar/?action=transfer&amount=100&to=205&nonce=29374920 而这个数字也会被保存到服务器。下次生成链接,数字则会发生变化。这时由于无法找到固定的可用的链接,CSRF也就失效了。
这种防御虽说解决了很多问题,但是在很多地方也有着许多劣势。比如GET转POST会导致用户无法使用“返回”操作,也会导致用户必须亲自点击发出请求。这在一些反复使用的地方就会显著增加复杂度。而NONCE则会花服务器的处理开销和内部存储,甚至过期时还需定时清理。有时检查链接请求的REFERER头部信息也能有效的过滤CSRF,但是对于没有REFERER的请求,是抛弃(会导致大批量的用户无法使用)还是默许(于是就没作用了),也成为了困难的选择。
或许想着这些开销,很多站点、网络应用就在一个地方进行了简化:登出链接。不同于上面的操作,登出链接是用户主动放弃高权限(登录状态),进入低权限状态(未登陆),所以在登出环节内不设防范并不会造成用户出现不必要的损失。于是我们能见到各种形如 http://abc.com/logout 的单向“干净”链接,而这些无害的链接则也同时没有任何保护。
说到这里就要讲讲基于CSRF的降权拒绝服务攻击。由于现在很多服务都会载入信息流(即别人的信息和自己的进行流整合)而且很多时候,外链一些图片是不可避免的,所以则会发生降权拒绝服务攻击。攻击通过刻意分享登出链接,让加载信息流的用户“被迫”放弃了登陆状态,而终止了后面的需要认证的步骤。一旦重新登陆,再次载入了恶意信息流,再次被动发出登出请求,再次被登出。如此反复,虽然并没有开放任何的安全隐患,但是短时间内大量的导致用户被迫登出而实现了拒绝服务攻击。
<img src="https://accounts.google.com/Logout?hl=en&continue=https://www.google.com/" />
三、这个到底和WEB APP有什么关系?
现在越来越多的网络应用正在冲入日常生活,然而这种不经意间的登出,或许会在短时间内造成困扰。由于降低权限并不构成很大的安全问题,所以CSRF的降权空间很大。大到Google的账号,小到人人网,一张图片足以瞬间登出。
看一看解释,是不是明白了这个似乎是BUG但是又不那么BUG的“漏洞”呢?
其实这同样属于XSS的说