小白也能征服CSRF

  • 英文:Cross Site Request Forgy
  • 中文:跨站请求伪造
  • 攻击者在其他的网站对目标网站产生了影响
CSRF攻击危害


  • 利用用户登录态
  • 用户不知情
  • 完成业务请求
  • 盗取用户资金(转账,消费)

就算警察寻找是谁,也只能找到用户,找不到攻击者,因为攻击者用的ip和cookie都是用户的。

CSRF攻击防御

csrf防御核心思想就是利用攻击者不会访问目标网站的前端,只会去访问目标网站的后端,所以如果在目标网站的前端增加验证信息,那就会有效防御csrf攻击,因为csrf无法获取这个验证信息,也就无法得到后端的正确响应。

第一种方法

禁止第三方网站携带cookie

在cookie中加一个same-site属性 但是兼容性很差,只有很少的浏览器兼容。

第二种方法

在前端页面加入验证信息,比如:
1. 验证码
2. 加入token

验证码

这需要前后端协同
1:前端加入验证码输入框。
2:后端为前端提供这个验证码,并且在提交的时候进行验证,还有后端还要记住这个验证码是什么,也就是保存下来,以便有第三方进行csrf攻击时进行判断。
node.js开发后端的话,有ccap这个插件可以用,它可以生成图形验证码。

这个可以有效防御csrf,但是每次都要让用户输入验证码进行验证,降低了用户体验。而且前端提交后,后端还要再校验一下验证码对不对。


token

token就是一个随机字符串,放在前端的请求内容中,也可以放在cookie中。

token生成机制:

// 后端要做的事情
// 随机生成token
var csrfToken = parseInt(Math.random() * 9999999, 10);

// 后端生成token并且保存在cookie中
ctx.cookies.set('csrfToken', csrfToken);


// 前端要做的事情
// 放置一个表单,不会显示出来,设置隐藏
<input name="csrfToken" value=csrfToken><input>
然后在相应的动作里进行判断:
function action(req, res){
    var data;
    if(req.method.toLowerCase() === 'post'){
      data = req.body;
    }else{
        data = req.query;
    }
    if(!data.crsfToken){
        throw new('csrf token is null');
    }else if(data.csrfToken !== req.cookies.get('csrfToken')){
        throw new('csrfToken 错误');
    }
}

使用token需要注意的地方

  • 如果是通过表单提交,则可以直接将token值放在表单里面提交。
  • 如果是ajax请求,则一般是通过将token放在页面的另外一个地方,比如放在meta中。
meta{name="csrf_token", content=csrfToken}

刷新后,在页面的head中多了一个meta,在ajax请求之前,就可以通过js把这个meta中的toke值取出来,一并发到后台去。

注意:

如果用户打开了很多页面或者很多提交表单,每个页面和表单都是对应不同的token,因为cookies里面只能放置一个token,用户提交只能是提交最后一个页面的token或者是最后一个表单的token,所以这个问题也比较特殊,如何处理。需要思考。


CSRF中的referer

referer是http协议中的一个请求头,来自攻击网站。所以还有一个防御方式:验证referer,禁止来自第三方网站的请求。

// 在相应的动作里
function action(req, res){
    var data;
    if(req.method.toLowerCase() === 'post'){
      data = req.body;
    }else{
        data = req.query;
    }
    var referer = res.headers.referer;
    // 通过使用indexOf判断
    if(referer indexOf('localhost') === '-1'){
        throw new('请求非法');
    }

    // 更好的做法是下面这个,因为referer是http://整个url地址,如果url其他部分有localhost,上面的表达式也可以被匹配到
    if(!/^http:\/\/localhost/.test(referer)){
        throw new('请求非法');
    }
}

这里面有几个注意的点:

  • 从本地磁盘访问,没有refere,因为是同域,可以将ftp改成http形式,比如http://127.0.0.1/
  • 通过http访问,有referer。

以上就是我个人对CSRF的理解,前端领域的Web安全所涉及到的内容是很多的,要多去学习和实践,才能更好的写出安全又没有漏洞的代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值