CSRF的检测与防御笔记

CSRF的检测

检测CSRF攻击主要分两种:手工检测和半自动检测。并不是说没有全自动的CSRF检测工具,只不过这玩意误报率比较大,所以就不做介绍了。

手工检测

在检测CSRF漏洞时,首先需要确定的一点是:CSRF只能通过用户的正规操作进行攻击,实际上就是劫持用户操作。所以,在检测前首先需要确定Web应用程序的所有功能,以及确定哪些操作是敏感的,比如修改密码、转账、发表留言等功能。

确定了敏感性操作后,使用这项“功能”并拦截HTTP请求,比如,如果删除用户操作URL为:

可以猜想,此时的参数项ID应该是用户的唯一标识信息,通过此ID可以删除指定的用户。在确定参数项的意义后,就可以验证该项功能是否存在CSRF漏洞。

编写CSRP POC为

打开这个HTML,JavaScript将自动提交这个form表单,当提交请求后,查看ID为5的用户是否被删除,如果被删除就可以确定存在CSRF漏洞。

半自动检测

在检测CSRF漏洞时,不像SQL注射、XSS漏洞那样,有时候必须要完全通过手动测试,而CSRF测试则不需要,CSRF漏洞最常用的是半自动检测。下面介绍常用的CSRF半自动检测工具:CSRFTester。这是一款OWASP组织提供的半自动CSRF漏洞测试工具,它可以拦截所有的请求,方便测试人员进行分析。

但我手里还没有这个软件,教程什么的估计有人系统地做过,就不在这多做笔记了。

CRSF的防御

二次确认

之前给我们讲信息安全的老师,准备手敲简单的注入代码给我们做实验,找几个网站,点进去一看见验证码就跑了。可见验证码的实用程度(其实还是嫌麻烦)。

验证码。这可以说是对抗CSRF攻击最简洁有效的防御方法。CSRF攻击的过程,往往是在用户不知情的情况下构造了网络请求。而验证码强制用户必须与应用进行交互,才能完成最终请求。因此在通常情况下,验证码能够很好地遏制CSRF攻击。但验证码不是万能的,你不能总跟用户弹验证码,正常做的业务干啥都要验证码,用户也会烦的。因此验证码只能作为一种辅助手段,不能算是主要的解决方案。

再次询问。其实道理跟验证码有点像,就多弹一个框,问:你确定要这么做吗?如果用户是被攻击的,冷不丁弹这一个窗口,肯定会有所警觉,赶紧关掉了。可能正是这一环节阻止了攻击的进行。而且相较于验证码来说对用户体验损伤不大,但怕的是用户习惯性地直接点确定,毕竟面对两个选项与输入一串字符相比,前者思考的时间往往要短一些。

Referer Check

Referer Check在互联网中最常见的应用就是“防止图片盗链”。同理,Referer Check也可以被用于检查请求是否来自合法的“源”。Referer就是HTTP请求里面的内容,忘了再去复习一下。

常见的互联网应用,页面与页面之间都具有一定的逻辑关系,这就使得每个正常请求的Referer具有一定的规律。比如一个“论坛发帖”的操作,在正常情况下需要先登录到用户后台,或者访问有发帖功能的页面。在提交“发帖”的表单时,Referer的值必然是发帖表单所在的页面。如果 Referer的值不是这个页面,甚至不是发帖网站的域,则极有可能是CSRF攻击。

即使我们能够通过检查 Referer是否合法来判断用户是否被CSRF攻击,也仅仅是满足了防御的充分条件。Referer Check 的缺陷在于,服务器并非什么时候都能取到Referer。很多用户出于隐私保护的考虑,限制了Referer 的发送。在某些情况下,浏览器也不会发送Referer,比如从HTTPS跳转到HTTP,出于安全的考虑,浏览器也不会发送 Referer。

在flash的一些版本中,曾经可以自定义Referer头。虽然Flash在新版本中已经加强了安全限制,不再允许这么做,但是别的客户端插件允许了怎么办。这么看来,Referer Check也无法作为防御CSRF的主要手段,但用于监控CSRF攻击是肯定可行的。

Anti CSRF Token

CSRF为什么能攻击成功?本质原因就是重要操作的所有参数都是能被攻击者猜测到。攻击只有预测出URL的所有参数与参数值,才能成功地构造出一个伪造的请求;反之,攻击者将无法攻击成功。由于这个原因可以想出一个解决方案:把参数加密,或者使用一些随机数,从而让攻击者无法猜测到参数值。这时不可预测性原则的一种应用。不可预测性在《安全方案的设计原则笔记》里介绍过。

比如说一个删除操作的URL是:

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

这样攻击者在不知道salt(什么是salt? 可见blog.csdn.net/acm_yuuji/article/details/27642221)的情况下,是无法构造出这个URL的,因此也就无从发起CSRF攻击了。而对于服务器来说,则可以从Session或Cookie中取得username=abc的值,再结合salt对整个请求进行验证,正常请求则会认为是合法的。

但是这个方法也存在一些问题。首先,加密或混淆后的URL将变得非常难读,对用户非常不友好。其次,如果加密的参数每次都改变,则某些URL 将无法再被用户收藏加书签。最后,普通的参数如果也被加密或哈希,将会给数据分析工作带来很大的困扰,因为数据分析工作常常需要用到参数的明文。

因此需要用一个更通用的法子,就是本节的题目 Anti CSRF Token。

Token即标志、记号的意思,在IT领域也叫令牌。

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

要使Token足够随机,必须使用足够安全的随机数生成算法,或者采用真随机数生成器。Token应该作为一个“秘密”,为用户与服务器所共同持有,不能被第三者知晓。在实际应用时,Token可以放在用户的Session中,或者浏览器的Cookie中。由于Token的存在,攻击者无法再构造出一个完整的URL实施CSRF攻击。Token需要同时放在表单和Session中。在提交请求时,服务器只需验证表单中的Token,与用户Session(或Cookie))中的Token是否一致,如果一致,则认为是合法请求;如果不一致,或者有一个为空,则认为请求不合法,可能发生了CSRF攻击。

Token的使用原则

该Token根据“不可预测性原则”所设计,所以该Token的生成一定要足够随机,需要使用安全的随机数生成器生成Token。

此外,这个Token的目的不是为了防止重复提交。所以为了使用方便,可以允许在一个用户的有效生命周期内,在Token消耗前都使用同一个Token。但是如果用户已经提交了表单,则消耗这个Token,重新生成一个新的Token。

如果Token保存在Cookie 中,而不是服务器端的Session 中,则会带来一个新的问题。如果一个用户打开几个相同的页面同时操作,当某个页面消耗掉这个Token后,其他页面的表单内保存的还是被消耗掉的那个Token,因此其他页面的表单再次提交时,会出现Token错误。在这种情况下,可以考虑生成多个有效的Token,以解决多页面共存的场景。

最后还应注意Token的保密性。如果Token出现在了页面的URL中,则可能会通过Referer的方式泄露。比如如下URL

这个manage页面是一个用户面板,用户需要在这个页面提交表单或点击“删除”按钮才能完成操作。在这种场景下,如果这个页面包含了一张攻击者能指定地址的图片

那么上面那个URL会作为HTTP请求的Referer发送到img标签里提到的网址服务器上,导致Token泄露。因此在使用Token时,应该尽量把Token放在表单中。把敏感操作由GET改为POST,以form表单(或者AJAX)的形式提交,可以避免 Token泄露。

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

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

参考资料:《白帽子讲web安全》吴瀚清

                  《Web安全深度剖析》张炳帅

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值