余晖落尽暮晚霞,黄昏迟暮远山寻
本站
当前位置:网站首页 > 编程知识 > 正文

JS Hook 攻防(JS hook)

xiyangw 2022-11-26 17:05 16 浏览 0 评论

1. 思考题

现有一款浏览器安全插件,会对所有页面的 Performance API 进行 Hook,以降低 JS 获取的时间精度,减少边信道攻击的风险。

该插件会把如下代码注入到页面最开始:

JS Hook 攻防(JS hook)

(function() {
  const obj = performance
  const rawFn = Performance.prototype.now

  Performance.prototype.now = function() {
    const val = rawFn.apply(obj, arguments)
    return ((val * 10) | 0) / 10
  }
})()

performance.now()    // 11346.9
performance.now()    // 12242.1

// 注:原始的 performance.now() 可获得小数点后多位

此外,包括 iframe 等子页面也会被注入该代码。

现在来思考,如何绕过这种防护方案,从而获得原生 performance.now 接口。(同时不损坏业务逻辑)

2. 攻

重写后的逻辑很简单,显然只能从 rawFn.apply 这里入手。

熟悉前端的应该都知道原型链的概念,例如 rawFn.apply === Function.prototype.apply,前者只是后者的一个引用而已。

所以,攻击者可重写 Function.prototype.apply 函数,然后故意调用一下 performance.now,触发 rawFn.apply,于是进入我们的 apply 函数。其中的 this 即 rawFn,就是我们想要的结果!

最后再将 Function.prototype.apply 恢复,不影响后续业务逻辑。

copyvar rawApply = Function.prototype.apply
var rawNow

Function.prototype.apply = function() {
  rawNow = this
}

performance.now()

Function.prototype.apply = rawApply

console.log('获得原始接口:', rawNow)
3. 防
作为插件的开发者,又该如何防范这种攻击?

显然,不能使用 rawFn.apply 这种潜在副作用的操作。ES6 提供了 Reflect API,可以更加原子地实现各种操作。

例如 document.createElement('DIV'),通过 Reflect 可这样调用:

Reflect.apply(document.createElement, document, ['DIV'])
由于 Reflect 下的方法都是静态方法,因此可将其备份到闭包内部的变量里,之后直接使用:

(function() {
  const apply = Reflect.apply

  const result = apply(document.createElement, document, ['DIV'])
  console.log(result)
})()
这样,即使攻击者重写了 Reflect.apply,我们也不受影响!

进一步,我们可将所有变量都提前备份,完全不依赖全局变量:

(function() {
  const document = window.document
  const createElement = document.createElement
  const apply = Reflect.apply

  const result = apply(createElement, document, ['DIV'])
  // ...
})()
换成本文开头的案例:

copy(function() {
  const obj = performance
  const rawFn = performance.now
  const apply = Reflect.apply

  Performance.prototype.now = function() {
    const val = apply(rawFn, obj, [])
    return ((val * 10) | 0) / 10
  }
})()

3. 防
作为插件的开发者,又该如何防范这种攻击?

显然,不能使用 rawFn.apply 这种潜在副作用的操作。ES6 提供了 Reflect API,可以更加原子地实现各种操作。

例如 document.createElement('DIV'),通过 Reflect 可这样调用:

Reflect.apply(document.createElement, document, ['DIV'])
由于 Reflect 下的方法都是静态方法,因此可将其备份到闭包内部的变量里,之后直接使用:

(function() {
  const apply = Reflect.apply

  const result = apply(document.createElement, document, ['DIV'])
  console.log(result)
})()
这样,即使攻击者重写了 Reflect.apply,我们也不受影响!

进一步,我们可将所有变量都提前备份,完全不依赖全局变量:

(function() {
  const document = window.document
  const createElement = document.createElement
  const apply = Reflect.apply

  const result = apply(createElement, document, ['DIV'])
  // ...
})()
换成本文开头的案例:

copy(function() {
  const obj = performance
  const rawFn = performance.now
  const apply = Reflect.apply

  Performance.prototype.now = function() {
    const val = apply(rawFn, obj, [])
    return ((val * 10) | 0) / 10
  }
})()

3. 防

作为插件的开发者,又该如何防范这种攻击?

显然,不能使用 rawFn.apply 这种潜在副作用的操作。ES6 提供了 Reflect API,可以更加原子地实现各种操作。

例如 document.createElement('DIV'),通过 Reflect 可这样调用:

Reflect.apply(document.createElement, document, ['DIV'])

由于 Reflect 下的方法都是静态方法,因此可将其备份到闭包内部的变量里,之后直接使用:

(function() {
  const apply = Reflect.apply

  const result = apply(document.createElement, document, ['DIV'])
  console.log(result)
})()

这样,即使攻击者重写了 Reflect.apply,我们也不受影响!

进一步,我们可将所有变量都提前备份,完全不依赖全局变量:

(function() {
  const document = window.document
  const createElement = document.createElement
  const apply = Reflect.apply

  const result = apply(createElement, document, ['DIV'])
  // ...
})()

换成本文开头的案例:

copy(function() {
  const obj = performance
  const rawFn = performance.now
  const apply = Reflect.apply

  Performance.prototype.now = function() {
    const val = apply(rawFn, obj, [])
    return ((val * 10) | 0) / 10
  }
})()

相关推荐

前后端分离 Vue + NodeJS(Koa) + MongoDB实践

作者:前端藏经阁转发链接:https://www.yuque.com/xwifrr/gr8qaw/vr51p4写在前面闲来无事,试了一下Koa,第一次搞感觉还不错,这个项目比较基础但还是比较完整了,...

MongoDB 集群如何工作?

一、什么是“MongoDB”?“MongoDB”是一个开源文档数据库,也是领先的“NoSQL”数据库,分别用“C++”“编程语言”编写,使用带有“Schema”的各种类似JSON的文档,是也分别被认为...

三部搭建mongo,和mongo UI界面

三步搭建mongo,和mongoUI界面安装首先你需要先有一个docker的环境检查你的到docker版本docker--versionDockerversion18.03.1-ce,b...

Mongodb 高可用落地方案

此落地方案,用于实现高可用。复制集这里部署相关的复制集,用于实现MongoDB的高可用。介绍MongoDB复制集用于提供相关的数据副本,当发生硬件或者服务中断的时候,将会从副本中恢复数据,并进行自动...

一次线上事故,我顿悟了MongoDB的精髓

大家好,我是哪吒,最近项目在使用MongoDB作为图片和文档的存储数据库,为啥不直接存MySQL里,还要搭个MongoDB集群,麻不麻烦?让我们一起,一探究竟,继续学习MongoDB分片的理论与实践,...

IDEA中安装MongoDB插件-再也无要nosql manager for mongodb

大家都知道MongoDB数据库作为典型的非关系型数据库被广泛使用,但基于MongoDB的可视化管理工具-nosqlmanagerformongodb也被用的较多,但此软件收费,所以国内的破解一般...

数据库监控软件Lepus安装部署详解

Lepus安装部署一、软件介绍Lepus是一套开源的数据库监控平台,目前已经支持MySQL、Oracle、SQLServer、MongoDB、Redis等数据库的基本监控和告警(MySQL已经支持复...

YAPI:从0搭建API文档管理工具

背景最近在找一款API文档管理工具,之前有用过Swagger、APIManager、Confluence,现在用的还是Confluence。我个人一直不喜欢用Swagger,感觉“代码即文档”,让代...

Mac安装使用MongoDB

下载MongoDB包:https://www.mongodb.com/download-center解压mongodb包手动解压到/usr/local/mongodb文件夹配置Mac环境变量打开环境...

保证数据安全,不可不知道的MongoDB备份与恢复

大家在项目中如果使用MongoDB作为NOsql数据库进行存储,那一定涉及到数据的备份与恢复,下面给大家介绍下:MongoDB数据备份方法在MongoDB中我们使用mongodump命令来备...

MongoDB数据备份、还原脚本和定时任务脚本

备注:mongodump和mongorestore命令需要在MongoDB的安装目录bin下备份脚本备份格式/usr/local/mongodb/bin/mongodump -h ...

等保2.0测评:mongoDB数据库

一、MongoDB介绍MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB是一个介于关系数据库和非关系数据库之间的产...

MongoDB入门实操《一》

什么是MongoDBMongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB是一个介于关系数据库和非关系数据库之...

Python安装PyMongo的方法详细介绍

欢迎点击右上角关注小编,除了分享技术文章之外还有很多福利,私信学习资料可以领取包括不限于Python实战演练、PDF电子文档、面试集锦、学习资料等。前言本文主要给大家介绍的是关于安装PyMongo的...

第四篇:linux系统中mongodb的配置

建议使用普通用户进行以下操作。1、切换到普通用户odysee。2、准备mongodb安装包,自行去官网下载。3、解压安装包并重命名为mongodb4.04、配置mongodbcdmongod...

取消回复欢迎 发表评论: