在公司的实际开发环节中碰到了csrf的问题,收到SRC的报告后,进行了修复。

CSRF(Cross Site Request Forgery)跨站请求伪造,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。这利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。

攻击方法

实际场景中,我们的网站架构是用一个node服务器来接收前台请求,获取cdn的静态资源后渲染前端,用户和前端交互过程中,对于后端的请求通过node转发给实际上的后端,响应用户的请求。
其中node服务器完成前端的登录认证和cookie、session状态的维护,后端不进行来源的验证,对于所有请求都会无条件的响应,只是在响应过程中通过前端给的session辨别具体的用户。

那么当某一个涉及到资源修改的请求时,比如为A.ke.com/modify/?des=malice&cost=1000des参数表示资源转移的目标,cost表示转移的数量,后端通过接收到的session判断是哪个用户发起的,即资源转移的来源是谁;当然这种场景涉及到资金或其他重要的东西时,会有些额外的保护措施,比如加验签。

这个请求并不需要打开html页面,直接是个get或者post请求,那么当Malice构造了这么一个请求,并发送给了Alice,后者不知情的情况下点开这个链接的话,后端就会认为是Alice主动发起的资源修改请求,马上执行完成,比如给Malice转账1000。

其中这个链接不一定是Alice直接点开的,有可能是Malice构造了一个钓鱼网站,看起来毫无问题,但实际上当Alice在事先登陆过A.ke.com的情况下访问了这个网站后,网页上的恶意代码就会自动替Alice给A.ke.com发送恶意请求,达到攻击的目的。

解决方案

验证HTTP Referer

在上面的攻击手段中,实际发起请求的来源都是Malice构造的恶意网站发起的,而HTTP的header中有一个Referer字段,用于表明浏览器是从哪个页面发起的这个请求,所以我们只要在后端加一个http的拦截器,校验每一个请求的这个header值就能判断是否为恶意请求了:正常请求的header值为A.ke.com/**,而恶意请求的这个header值就会是malice.com/**,通过域名或者前缀校验即可。

这个方法最简单,只需要在node层加一个转发时的参数和后端的一个http拦截器,不需要修改具体的业务代码;但是,这种安全性是基于浏览器的安全性的,当浏览器对于referer的安全性无法保障时,这种方法也就没有效果。

表单中添加csrf token

HTTP 自定义header

参考