防范CSRF网络安全漏洞
什么是CSRF
在了解CSRF之前,我们需要先科普一下两个前提条件。首先,检查登录权限的方法有很多。目前大多数网站仍然采用会话任务方式。简单来说,session机制就是服务器使用键值对来记录登录信息,而cookie中保存的是cookie的session ID(刚才提到的key)。另外,我们还知道浏览器中的HTTP(s)请求会自动为我们将cookie传输到服务器。这样每次请求时都通过cookie获取session ID,然后通过它从服务器获取登录信息,完成用户权限的验证。
本来这也是一个很好的功能。但是由于cookie过于开放,如果用户登录A网站,如果用户在访问B网站时向A网站发送请求,那么这个请求实际上携带了用户的登录信息到A网站。如果此时用户不知道B站对A网站的请求,那将是非常严重的损失。上述过程就是一次跨站请求攻击,即Cross-Site Request Forgery或CSRF。
CSRF危险
小结 CSRF漏洞是利用网站权限检查中的漏洞,在用户不知情的情况下发送请求,达到“屏蔽”用户的目的。 CSRF攻击者进行的攻击主要类型如下:
- 攻击者可以诱骗受害者用户完成受害者允许的任何状态更改操作,例如更新帐户信息、完成购买、注销,甚至登录 .
- 获取用户隐私信息
- 配合其他漏洞攻击
- CSRF蠕虫
其中CSRF蠕虫,顾名思义,会造成蠕虫效应,将CSRF攻击扩展到数十、数百种。例如,社区私信好友接口和检索好友列表接口都存在CSRF漏洞。攻击者可以将它们组合成CSRF蠕虫——当用户访问恶意页面时,通过CSRF获取好友列表信息,然后利用好友CSRF私人消息漏洞向每个好友发送指向恶意页面的消息。只要有人查看该邮件中的链接,CSRF蠕虫就会不断传播,其造成的危害和影响是巨大的!
防御方法
从上面的描述中,我们可以知道CSRF有两个特点:利用cookie自动传输功能和攻击。那么您可以针对这两个功能使用以下解决方案。
检查Referer字段
大家都知道HTTP头中有一个Referer字段。该字段用于指示请求来自的地址。通过查看网站上的这个请求字段,我们可以知道该请求是否是从这个网站发出的。我们可以拒绝任何不是由该站点发出的请求,从而避免跨站点 CSRF 功能。
const { parse } = require('url');
module.exports = class extends think.Logic {
indexAction() {
const referrer = this.ctx.referrer();
const {host: referrerHost} = parse(referrer);
if(referrerHost !== 'xxx') {
return this.fail('REFERRER_ERROR');
}
}
}
复制代码以ThinkJS为例,在Logic中做一个简单的判断。此方法利用了客户无法创建引荐来源网址的事实。虽然简单,但是如果网站有多个域名或者域名经常变化并且还有一定的限制,那就会变得非常困难。
令牌验证
由于CSRF利用了浏览器自动传递cookie的能力,因此另一个安全思想是不通过cookie传递身份验证数据,而将随机加密字符串添加到其他身份验证参数中。这里有两种方法:
- 随机字符串:为每次提交添加随机字符串参数。服务器通过页面发送该参数。每次请求时都会将其添加到广播参数中。服务器检查参数。通过参数是否一致来判断是否是用户请求。由于在CSRF攻击中攻击者无法提前知道随机字符串的值,因此服务器可以通过检查该值来拒绝请求。
- JWT:事实上,除了登录会话之外,使用 JWT 令牌验证登录也变得越来越流行。该方法在前端注册登录令牌,并通过在每个请求的标头中添加身份验证标头来执行登录验证过程。由于在CSRF攻击中攻击者无法知道令牌的价值,因此也可以通过这种方式来防止CSRF攻击。有关在 ThinkJS 中使用 JWT 的信息,请参阅之前的文章《ThinkJS JWT 鉴权实践》。当然,除了JWT之外,令牌登录方式还包括OAuth等多种方式。
后记
除了上面提到的cookie登录问题导致的CSRF攻击之外,添加、删除、修改等操作都是通过GET请求完成的。如果请求没有验证登录信息,也很容易引发CSRF攻击。当然,这是一个比较低的水平,但仍然需要引起重视。尤其是当前SPA的流行以及AJAX请求的不断增加,我们需要警惕CSRF攻击的可能性。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网
