CSRF

Cross Site Request Forgy
跨站请求伪造

CSRF攻击与防御 Safe 第1张

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

需要条件

  • 用户登录 A 网站
  • A 网站确认身份
  • B 网站页面向 A 网站发起请求(带 A 网站身份)

CRSF 攻击危害

  • 利用用户登录态---盗取用户资金(转账,消费)
  • 用户不知情---冒充用户发帖背锅
  • 完成业务请求---损坏网站名誉
  • ...

CSRF 攻击防御

  • 过程:

    • B 网站向 A 网站请求
    • 带 A 网站 Cookies
    • 不访问 A 网站的前端
    • referer 为 B 网站(这里的 referer 为为数不多的错误单词)
  • 禁止第三方网站带 Cookies,为 Cookies 设置 Same-site 属性

koa 设置方式

ctx.cookies.set("userId", user.id, {
  httpOnly: false,
  sameSite: "strict"
});

这种方法较好但是,有些浏览器不支持,但将来应该会的

CSRF攻击与防御 Safe 第2张

  • 不访问 A 网站的前端
    • 在前端页面加入验证消息
    • 验证码
    • 安装第三方插件生成验证码
    • 运行npm install ccap --save
captcha.captcha = async function(ctx, next) {
  var ccap = require("ccap");
  var capt = ccap();
  var data = capt.get();

  captcha.setCache(ctx.cookies.get("userId"), data[0]);
  ctx.body = data[1];
};

// 设置
captcha.setCache = function(uid, data) {
  console.log(uid, dtat);
  cache[uid] = data;
};

//验证
capthcha.validCache = function(uid, dtat) {
  return cache[uid] === data;
};

下面调用上面

console.log(data.captcha);

//没有验证码
if (!data.captch) {
  throw new Erroe("验证码错误");
}

//验证码不匹配
var captcha = require("../tools/captcha");
var result = captcha.validCache(ctx.cookies.get("userID"), data.captcha);
console.log("result", result);
if (!result) {
  throw new error("验证码错误");
}
  • 不访问 A 网站的前端
    • 在前端页面加入验证消息
    • token

验证码有时是会影响用户体验的,所以就有了 taken,一般为隐藏的文本框

var csrfToken = parseInt(Math.random() * 99999999, 10);
ctx.cookies.set("csrfToken", csrfToken);

//渲染时
ctx.render("post", { post, comments, csrfToken });

验证

if (!data.crsfToken) {
  throw new Error("CSRF Token 为空");
}
if (data.csrfToken !== ctx.cookies.get("csrfToken")) {
  throw new Erroe("CSRF Token错误");
}

ajax 做法
html 头部

<meta http-equiv="X-UA-Compatible" content="csrfToken" name="csrf_token" />

referer 为 B 网站

  • 验证 referer
  • 禁止来自第三方网站的请求
var referer = ctx.request.header.referer;
// console.log(ctx.request.header, referer);
if(!^https?:\/\/loaclhost/.test(referer)){
// if(referer.indexOf('localhost')===-1)//验证不全面,所以要采用上面的做法
  throw new Error('非法请求')
}
扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄