一个运行快两年的express框架web系统,被安全部门审核存在csrf漏洞,项目使用的前后端分离的形式,所有功能操作,通过ajax调用后端接口来完成,查了很多资料,一个基本的防御思想就是验证随机数了,为什么随机数就可以实现csrf的防御呢?本文将针对该问题进行分解
什么是csrf
csrf(跨站请求伪造)是一种网络攻击方式,怎么实现这种攻击方式呢?
1.登录受信任网站A,并在本地生成Cookie
2.在不登出A的情况下,访问危险网站B,B站存在一个针对A站恶意的路由操作,如删除某条记录
用户操作后,就会删除造成对A站的攻击
如果不满足以上两个条件中的一个,就不会受到CSRF的攻击
示例1:
银行网站A,它以GET请求来完成银行转账的操作,如:http://www.mybank.com/Transfer.php?toBankId=11&money=1000
危险网站B,它里面有一段HTML的代码如下:
<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>
首先,你登录了银行网站A,然后访问危险网站B,噢,这时你会发现你的银行账户少了1000块......
虽然存在着巨大的不确定性,但是这种漏洞危害性也是巨大的
csrf的防御策略
针对以上的攻击方式,我们要采取防御措施
- 验证 HTTP Referer 字段
HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,比如需要访问 http://bank.example/withdraw?...,用户必须先登陆 bank.example,然后通过点击页面上的按钮来触发转账事件。这时,该转帐请求的 Referer 值就会是转账按钮所在的页面的 URL,通常是以 bank.example 域名开头的地址。而如果黑客要对银行网站实施 CSRF 攻击,他只能在他自己的网站构造请求,当用户通过黑客的网站发送请求到银行时,该请求的 Referer 是指向黑客自己的网站。因此,要防御 CSRF 攻击,银行网站只需要对于每一个转账请求验证其 Referer 值,如果是以 bank.example 开头的域名,则说明该请求是来自银行网站自己的请求,是合法的。如果 Referer 是其他网站的话,则有可能是黑客的 CSRF 攻击,拒绝该请求。
由于Referer可以篡改,所以这种方案安全性较低。
- 验证码的方式
每一次操作前添加验证码,该种方案较繁琐,一般不会采用。
- 随机数验证
现在csrf防御主要采用该种方式,基本流程
- 服务端产生一个随机数,发送到客户端
- 客户端在表单提交时,携带该随机数
- 在服务端验证该随机数
基本的防御思想就是这样的流程,那么怎么来怎么实现这样的业务代码。
由于项目是一个老的系统,所以采取切面处理的方式,
- 在服务端生成一个随机数csrf,然后加密生成csrftoken,然后将这两个值发送到客户端
- 在请求时将header中携带csrftoken
- 服务端验证加密后csrf和csrftoken是否相等
该种方案略显复杂,精简一下
- 服务生成一个随机数token,设置cookie
- 在客户端生成经过md5(token)生成一个csrftoken,在请求时携带在header中
- 在服务端,取cookie中的token,经过md(token)算法后和header中的csrftoken做比较
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。