当前位置: 首页 > news >正文

每个 node 应用可能存在的 timing-attack 安全漏洞

前言

假如你在项目中遇到过 eslint 报错 Potential timing attack ,不可忽视!这是一个涉及到安全的问题:时序攻击。

eslint 报错原因

  • 首先eslint引入了一个叫做eslint-plugin-security的插件,这个插件有助于识别出潜在的安全问题,但同时也会产生误报的问题,附上插件 源码地址。
  var keywords = '((' + [
    'password',
    'secret',
    'api',
    'apiKey',
    'token',
    'auth',
    'pass',
    'hash'
  ].join(')|(') + '))';

  var re = new RegExp('^' + keywords + '$', 'im');

  function containsKeyword (node) {
    if (node.type === 'Identifier') {
      if (re.test(node.name)) return true;
    }
    return
  }


  if (node.test.operator === '==' || node.test.operator === '===' || node.test.operator === '!=' || node.test.operator === '!==') {
    // 在这里 console 出错误
  }
复制代码

首先这个插件会判断本次的运算符是否为 ==、===、!=、!==其中一种,其次检查标识符(字段名)是否包含特殊字符串password、secret、api、apiKey、token、auth、pass、hash,如果同时满足二者情况,eslint 就会编译报错 Potential timing attack

攻击定义

timing attack:时序攻击,属于侧信道攻击 / 旁路攻击,侧信道攻击指的是利用信道外的信息,比如加解密的数据、数据比较时间、密文传输的流量和途径进行攻击的方式,相当于是“旁敲侧击”。

攻击点

  • 首先讲讲js比较两个字符串大小的原理:

    • 判断字符串长度是否为0,如果为0,就可以直接比较出结果;反之,进入到第二步。
    • 字符串是由一个个字符组成,通过每个字符的charCode进行比较。
    • 在第二步中,只要出现一个字符不同,就 return false,剩余的字符不再做比较。
  • 单个字符的比较是很快的,攻击者可以细化测量时间精度到微秒,通过响应时间的差异推算出是从哪一个字符开始不用的,这样一次次实验或者用 Python 写个脚本去跑,就可以试出正确的密码,密码破解的难度也降低了不少。

容易受攻击的写法

  if (user.password === password) {
    return { state: true }; // 登录成功
  }
复制代码

防御措施

每次不同的输入会造成处理时间的不同。为了防止它,我们需要使字符串比较花费相同的时间量,无论输入的密码是什么。

不容易受攻击的写法

系统中每一个密码的长度是固定的,每次比较密码是否相同时,使用正确密码的长度作为比较次数,使用异或比较每一个字符的 Unicode 编码是否相等,并且把每一次的比较结果存放到一个数组中,最后再判断数组的每一个元素是否为0(为 0 表示两个字符相同)

  // psdReceived 为用户输入密码;
  // psdDb 为系统中存储的正确用户密码
  const correctUser = (psdDb, psdReceived) => {
    const state = [];
    for (let i = 0; i < psdDb.length; ++i) {
      if (!psdReceived[i]) {
        state.push(false);
      } else {
        state.push(psdReceived.charCodeAt(i) ^ psdDb.charCodeAt(i));
      }
    }
    return state.length !== 0 && state.every(item => !item);
  }
复制代码

三方包推荐

也可以使用 cryptiles 这个 npm 模块来解决这个问题

import cryptiles from 'cryptiles';

......
return cryptiles.fixedTimeCimparison(passwordFromDb, passwordReceived);
复制代码

关注微信公众号:创宇前端(KnownsecFED),码上获取更多优质干货!

相关文章:

  • 自己做的js甘特图插件
  • 流式计算与计算抽象化------《Designing Data-Intensive Applications》读书笔记15
  • codis proxy处理流程
  • 【异周话题 第 20 期】三年后,人工智能将彻底改变前端开发?
  • IOS评论框不贴底(ios12新bug)
  • iOS点击获取短信验证码按钮
  • 快速开始Python/WSGI应用程序
  • JavaScript原生实现《贪吃蛇》
  • JPA关系映射系列二:one-to-one主键关联
  • CSS选择器——伪元素选择器之处理父元素高度及外边距溢出
  • 有了这四个“最”,AI或许可以成功预测地震
  • JS设计模式之工厂模式
  • Web前端开发必备手册(Cheat sheet)
  • 如何在招聘中考核.NET架构师
  • 《ActiveMQ 系列》- HelloWorld
  • [NodeJS] 关于Buffer
  • 【162天】黑马程序员27天视频学习笔记【Day02-上】
  • Golang-长连接-状态推送
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • js操作时间(持续更新)
  • Python利用正则抓取网页内容保存到本地
  • Rancher-k8s加速安装文档
  • SAP云平台里Global Account和Sub Account的关系
  • SpiderData 2019年2月23日 DApp数据排行榜
  • win10下安装mysql5.7
  • 安卓应用性能调试和优化经验分享
  • 从0实现一个tiny react(三)生命周期
  • 反思总结然后整装待发
  • 聊聊directory traversal attack
  • 前嗅ForeSpider采集配置界面介绍
  • 软件开发学习的5大技巧,你知道吗?
  • 数据可视化之 Sankey 桑基图的实现
  • 积累各种好的链接
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • # .NET Framework中使用命名管道进行进程间通信
  • # centos7下FFmpeg环境部署记录
  • #{}和${}的区别是什么 -- java面试
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • (16)Reactor的测试——响应式Spring的道法术器
  • (1综述)从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练
  • (C语言)求出1,2,5三个数不同个数组合为100的组合个数
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (九十四)函数和二维数组
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (一)WLAN定义和基本架构转
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • *(长期更新)软考网络工程师学习笔记——Section 22 无线局域网
  • **PHP二维数组遍历时同时赋值
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .net Signalr 使用笔记
  • .NET 编写一个可以异步等待循环中任何一个部分的 Awaiter
  • .net 程序 换成 java,NET程序员如何转行为J2EE之java基础上(9)
  • .NET 除了用 Task 之外,如何自己写一个可以 await 的对象?