CSRF攻击及其防御

宜未雨而绸缪,毋临渴而掘井。

CSRF的全名是(Cross Site Request Forgery),中文为跨站点请求伪造。CSRF是一种诱使受害者在有漏洞的WEB应用上用他自己的自己的会话执行其非预期操作的攻击手段。和大部分XSS攻击的目的是窃取信息不同,CSRF的攻击目的是为了提交改变状态的请求。事实上,CSRF的攻击者不能也不必看到请求的响应。

01

CSRF攻击实例

让我们设想一个有CSRF漏洞的银行Leak Bank。通过对银行网站发送请求http://www.leakbank.com/transfer?account=Andy&amount=1000&to=Bob, Andy可以把1000元转账给Bob。黑客Carl在Leak Bank开了一个账户,想偷取Andy的钱,他可以尝试发送请求http://www.leakbank.com/transfer?account=Andy&amount=1000&to=Carl, 但这个请求来自Carl自己,不是来自Andy,所以会授权失败。

这时Carl想起可以利用CSRF漏洞。通过一点社会工程学,比如在自己的网站上放个内涵图片啥的,受害者Andy不幸点了某个链接,替Carl提交了请求。这时上述URL会从Andy的浏览器发向Leak Bank,而这个请求会附上Andy浏览器中的cookie一起发向银行服务器。在大多数情况下这个请求会失败,因为这需要Andy的认证信息。但如果Andy刚访问过Leak Bank,并且Session仍然有效的话,悲剧就诞生了。Andy的1000块钱在他毫不知情的情况下被转移到了Carl的账户。即使有朝一日他察觉了,去银行查询日志,也只能看到曾经由一个来自他本人的合法请求转移了这笔钱。

02

CSRF的防御

验证码

验证码强制了用户必须和应用交互才能完成请求。因此在通常的情况下,能很好地防止CSRF。但是验证码的用户体验太差,在企业应用里一般不能考虑这种做法。

Referer check

HTTP Header中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。比如访问 http://www.leakbank.com/transfer?account=Andy&amount=1000&to=Bob,用户须先登陆www.leakbank.com,然后通过点击页面上的按钮来触发转账事件。这时,该转帐请求的 Referer 值就会是转账按钮所在的页面的 URL,通常是以www.leakbank.com域名开头的地址。而Carl诱使Andy提交的请求的Referer则是Carl的网站上的某个URL。因此Leak Bank只需要对于每一个转账请求验证其 Referer值,如果不是以www.leakbank.com开头的域名,拒绝该请求。

然而,这种方法有其缺点。首先,在某些浏览器上黑客有可能篡改Referer。其次,因为Referer 值会记录下用户的访问来源,有些用户认为这样会侵犯隐私,因此设置浏览器使其在发送请求时不再提供 Referer。当他们正常访问银行网站时,Leak Bank会因为没有 Referer 值而拒绝合法请求。

Anti CSRF Token

CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中。要抵御 CSRF,需要在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。因此可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则拒绝该请求。

这种方法的难点在于如何把 token 以参数的形式加入请求。我们的做法是三管齐下,

通过修改form的prototype在submit前注入token

通过document.ready的listener来为动态创建的form注入token

通过修改tag来注入token

用HTTP Header 自定义属性验证

和上一种方法类似,不同之处在于 token 不是以参数的形式置于 HTTP 请求之中,而是在 HTTP Header中自定义属性里。通过 XMLHttpRequest 这个类,可以给所有该类请求加上 csrftoken 这个 HTTP Header属性,并设置 token 值。这样能免除上一种方法的种种不便,然而本方法的局限性非常大。XMLHttpRequest 请求通常用于 Ajax 方法中对于页面局部的异步刷新,并非所有的请求都适用。

注:鉴于暴露产品代码有违反SBC之嫌,这次就不贴代码了(前几次帖子也将逐一整改),请感兴趣的同学自己去git找源码看

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180523G08EI200?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券