CSRF跨站请求伪造

跨站请求伪造通常缩写为CSRF或者XSRF,是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。跟跨网站脚本XSS相比,XSS利用的是用户对指定网站的信任,CSRF利用的是网站对用户浏览器的信任,浏览器对于同一domain下所有请求会自动携带cookie

原理

  1. 用户A正常打开网站B,并且成功登录获取cookie

  2. 用户A未退出网站B,在同一个浏览器中打开新的TAB访问了网站C

  3. 网站C的页面存有一些攻击性的代码,会发出对于网站B的一个访问请求。

  4. 浏览器收到请求后,在用户不知情的情况下携带cookie访问网站B,导致网站B以用户A的权限处理请求。

实例

小明在某银行有存款,通过GET表单请求http://bank.example/withdraw?uid=1&amount=100&for=2就可以向账户2转账100,当对银行发起这个请求后,首先会验证cookie是否有合法的session才进行数据处理。
小黑近期无聊,就自己做了一个网站,利用某些标签允许跨域请求资源的策略,在自己的网站中构造<img src="http://bank.example/withdraw?uid=1&amount=100&for=2">,并通过广告、游戏等方式诱导小明点击进入这个网站,此时浏览器会携带cookie访问银行网站。在大部分情况下,这个请求并不会成功被执行,因为他并没有小明的认证信息,但是如果此时恰好小明刚刚访问了银行,此时服务端session尚未过期,这个url就会被正常响应,转账就会被执行。

防御

验证码

对于敏感操作加入验证码,强制用户与网站进行交互,能很好遏制CSRF攻击。

避免使用GET

GET接口太容易被拿来做CSRF攻击,只要构造一个<img>标签,而<img>标签又是不能过滤的数据。接口最好限制为POST使用,GET则无效,降低攻击风险。当然强制POST只是降低了风险,攻击者只要构造一个<form>就可以,但需要在第三方页面做,这样就增加暴露的可能性。

检查Referer字段

HTTP协议有一个Referer字段,记录了该HTTP请求的来源地址,浏览器限制其改动,最多将其设置为空rel="noreferrer",当然如果不是在浏览器中发起HTTP请求是可以随意改动这个字段的。
同样以小黑的CSRF攻击为例,假如小黑诱导小明的网站为www.black.com,那么对于其构建的CSRF攻击请求的Refererwww.black.com,而正常情况下应该为http://bank.example域名开头的一个链接,检测其不正确或者为空即拒绝响应。
但是这种方法也有一定的局限性,某些旧版本的浏览器比如IE6可以篡改Referer字段,有些用户认为Referer字段会侵犯他们的隐私,从而关闭了浏览器发送Referer,正常访问网站会被误认为为CSRF而拒绝响应。

加入Token验证字段

CSRF攻击之所以能够成功,是因为浏览器自动携带cookie进行请求,该请求中所有的用户验证信息都是存在于cookie中,由此可以完全伪造用户的请求。要抵御CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于cookie之中。
在请求头中加入一个Token字段,浏览器并不会自动携带Token去请求,且Token可以携带一段加密的jwt用作身份认证,这样进行CSRF的时候仅传递了cookie,并不能表明用户身份,网站即拒绝攻击请求。

每日一题

https://github.com/WindrunnerMax/EveryDay