CSRF攻防基础讲解

CSRF攻击

  • Cross-site request forgery
  • 跨站请求伪造

场景模拟

在用户登陆某个网站后,看到某篇文章高兴之余,挥手打字,忽然有人发来一个连接,登陆者打开连接后什么都没有操做或者只是好奇的点击了某个按钮,在原登陆网站评论页多出了一条本身的评论记录???what happened?
若是您或者您的朋友发生了这样的事情,那么请第一时间邮件反馈给网站维护者,您大几率多是被攻击了,而这种攻击就是CSRF,下面逐步介绍其攻击原理和防范措施。html

攻击原理

  1. 用户登陆A网站
  2. A网站登陆成功后返回用户身份信息
  3. B网站获取A网站的用户登陆身份信息向A网站发起请求,而且携带了A网站的用户身份信息

CSRF攻击原理.png

攻击危害

  • 利用用户登陆态前端

  • 用户不知情ios

  • 完成业务请求正则表达式

  • ...shell

  • 盗取用户资金(转帐、消费)axios

  • 冒充用户发帖背锅后端

  • 我的隐私泄露跨域

CSRF 攻击防护

禁止第三方网站带Cookies

sameSite

samesite是HTTP响应头Set-Cookie的属性之一。它容许您声明该Cookie是否仅限于第一方或者同一站点的访问。
SameSite接受下面三个值:浏览器

  • Lax

Cookies容许与当前网页的URL与请求目标一致时发送,而且与第三方网站发起的GET请求也会发送。浏览器默认值。安全

Set-Cookie: userId=123; SameSite=Lax;
复制代码
  • Strict

Cookies只会在当前网页的URL与请求目标一致时发送,不会与第三方网站发起的请求一块儿发送。

Set-Cookie:userId=123;SameSite=Strict
复制代码
  • None

Cookie将在全部上下文中发送,即容许跨域发送。
使用None时,必须同时设置Secure属性(Cookie只能经过HTTPS协议发送),不然无效。

如下的设置无效:

Set-Cookie: userId=123; SameSite=None
复制代码

下面的设置有效:

Set-Cookie: userId=123; SameSite=None;Secure
复制代码

更多用法能够参考阮一峰老师SameSite属性介绍MDN-SameSite,到此读者可能会疑惑 sameSite难道能够解决全部的CSRF攻击吗?
答案:固然不是,sameSite受浏览器兼容性的影响,并不能解决防护全部攻击。兼容性列表在MDN的连接中。
再按照攻击原理所理解,CSRF的攻击是不通过目标网站的前端的,那么咱们是否是能够在此处“动手脚”尼?

在前端页面加入验证信息

验证码


处理思路:后端生成验证码保存并传递给前端;在前端提交表单数据中加入验证码并提交,在后端校验验证码存在和正确与否;

//验证码生成
var captcha = {};
var cache = {};
captcha.captcha = async function (ctx, next) {
    var ccpa = require('ccap');//验证码生成模块
    var capt = ccpa();
    var data = capt.get();
    captcha.setCache(ctx.cookies.get('userId'), data[0]);
    ctx.body = data[1]
}
captcha.setCache = function (uid, data) {
    cache[uid] = data;
}
captcha.validCache = function (uid, data) {
    return cache[uid] === data;
}
module.exports = captcha;
复制代码
//验证码校验
...
const data = ctx.request.body;
if(!data.captcha){
	throw new Error('验证码错误')
}
var captcha = require('../tools/captcha')
var resultCaptche = captcha.validCache(ctx.cookies.get('userId'),data.captche);
if(!resultCaptche){
	throw new Error('验证码错误')
}
...
复制代码

加入图形验证码对防护攻击能够起到很好的做用,可是每一个表单都须要输入图形验证码且还要保证每次输入的验证码都正确。这对于用户来讲是很是痛苦的一件事,因而可知这种方式在实际的使用中并不受用,那么有没有其余的更好的方案尼?

token验证


token实际上是一段随机的字符串,它的做用是让攻击者发起请求时没有办法获取这个字符串,也就是必需要通过咱们的页面,通过目标网站的前端。

  • 在 HTTP 请求中以參数的形式添加一个随机产生的 token,并在服务器端验证这个 token,假设请求中没有token 或者 token 内容不对,拒绝该请求。
  • 在HTTP请求头中,经过axios的配置参数,给全部的fetch请求所有加上Token这个HTTP请求头属性,并把Token值也放入请求头中。
//fetch.js
import axios from 'axios';

function getToken() {
    return localStorage.getItem('Token') ||'';
}
const fetch = axios.create({
    timeout: 60000 
});
fetch.interceptors.request.use(
    config => {
        config.headers['X-Token'] = getToken(); 
        return config;
    },
    error => {
        closeLoding();
        Promise.reject(error);
    }
);
...
export default fetch;
复制代码

关于Token

  1. Token能够保存在localStorage中
  2. Token加密且签名
  3. Token生成与过时机制
  4. 将 JSON Web Tokens 应用到 OAuth 2

Referer

  • 验证referer
  • 禁止第三方网站的请求
// 校验代码
const referer = ctx.request.headers.referer;
// 简易防护
if(referer.indexOf('localhost')=== -1){
	throw new Error('非法请求')
}
上面的防护对这个地址是无效的:http:xx.xx.xx?name="张三"&uid='112'&localhost=='哈哈哈'
// 正则表达式防护
if(!/^https?:\/\/localhost/.test(referer)){
	throw new Error('非法请求')
}
复制代码

固然这里还要考虑没有referer的状况哈

结语

安全做为系统的壁垒,重要程度不用多说。 CSRF攻击更是安全防护的重中之中。 本文记录的是笔者在开发过程当中遇到的问题及处理的思路。可供有相似问题的读者参考。 其余安全方面的文章笔者会持续更新,欢迎各位读者提出意见和建议。

相关文章
相关标签/搜索