资讯专栏INFORMATION COLUMN

NPM酷库:vm2,安全的沙箱环境

pkhope / 1988人阅读

摘要:而标准库中的是不安全的,用户脚本可以轻易突破沙箱环境,获取主程序的上述代码在执行时,程序在第二行就直接退出,虚拟机环境中的代码逃逸,获得了主线程的变量,并调用,造成主程序非正常退出。

NPM酷库,每天两分钟,了解一个流行NPM库。

今天我们要了解的库是 vm2,则是一个Node.js 官方 vm 库的替代品,主要解决了安全问题。

不安全的vm

在Node.js官方标准库中有一个vm库,用来在V8虚拟机环境中编译执行JS代码。通常,我们用vm库来实现一个沙箱,在代码主程序之外执行额外的JS脚本。

有时,我们需要vm虚拟机来执行不受信任的代码,这些代码可能是由用户提交的,比如在脉冲云接口文档管理中,允许用户提交Mock.js脚本生成模拟接口数据。而Node.js标准库中的vm是不安全的,用户脚本可以轻易突破沙箱环境,获取主程序的Context!

const vm = require("vm");
vm.runInNewContext("this.constructor.constructor("return process")().exit()");
console.log("Never gets executed.");

上述代码在执行时,程序在第二行就直接退出,vm虚拟机环境中的代码逃逸,获得了主线程的 process 变量,并调用 process.exit(),造成主程序非正常退出。

vm不安全的原因

上文中的代码使用了runInNewContext函数简写,等价于如下代码:

const vm = require("vm");

const sandbox = {};
const script = new vm.Script("this.constructor.constructor("return process")().exit()");
const context = vm.createContext(sandbox);

script.runInContext(context);

console.log("Never gets executed.");

从代码中得知,创建vm环境时,首先要初始化一个对象 sendbox,这个对象就是vm中脚本执行时的全局环境Context,vm 脚本中全局 this 指向的就是这个对象。

而vm中脚本等同于:

const sandbox = this; // 获取Context
const ObjectConstructor = this.constructor; // 获取 Object 对象构造函数
const FunctionConstructor = ObjectConstructor.constructor; // 获取 Function 对象构造函数
const myfun = FunctionConstructor("return process"); // 构造一个函数,返回process全局变量
const process = myfun();
process.exit();

从上边脚本中可以看出vm不安全的原因。vm内部脚本的Context对象是在主程序中定义的,根据JS原型链原理,可以轻松获取主程序中的 Function 对象,用主程序的 Function 对象构造一个函数,那么这个函数运行时,就是在主程序闭包环境中执行的!所以,我们轻易地获取到了主程序的全局对象 process,最终控制主程序!

安全的vm2

vm2就是专门为了解决vm的安全问题而诞生的。

const { VM } = require("vm2");
const vm = new VM({
    timeout: 1000,
    sandbox: {}
});

vm.run(`process.exit()`); // TypeError: process.exit is not a function
vm2 特性:

运行不受信任的JS脚本

沙箱的终端输出信息完全可控

沙箱内可以受限地加载modules

可以安全地向沙箱间传递callback

死循环攻击免疫 while (true) {}

vm2 原理:

首先,vm2基于vm,使用官方的vm库构建沙箱环境。然后使用JavaScript的Proxy技术来防止沙箱脚本逃逸。

参考资料

VM2 https://github.com/patriksime...

Proxy https://developer.mozilla.org...

欢迎关注公众号:梁兴臣

每天了解一个NPM库,一年后成为Node.js高手

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/90602.html

相关文章

  • 为 Node.js 应用建立一个更安全沙箱环境

    摘要:当运行函数的时候,只能访问自己的本地变量和全局变量,不能访问构造器被调用生成的上下文的作用域。如何建立一个更安全一些的沙箱通过上文的探究,我们并没有找到一个完美的方案在建立安全的隔离的沙箱。 showImg(https://segmentfault.com/img/remote/1460000014575992); 有哪些动态执行脚本的场景? 在一些应用中,我们希望给用户提供插入自定义...

    cartoon 评论0 收藏0
  • NPM酷库:dotenv,从文件加载环境变量

    摘要:酷库,每天两分钟,了解一个流行库。今天我们要了解的就是一个可以使得从文件中加载环境变量的库,使用,我们只需要将程序的环境变量配置写在文件中。 NPM酷库,每天两分钟,了解一个流行NPM库。· 我们经常需要Node.js程序运行时加载不同的配置,比如开发环境和生产环境的数据数据库配置就可能不一样,使用 process.env.DB_HOST 环境变量,可以在Node.js程序内部方便获取...

    wanghui 评论0 收藏0
  • NPM酷库:debug,控制调试日志

    摘要:今天我们要了解的库是,一个专门用来控制输出调试日志的库。但是,随着项目规模增加,控制台输出的日志就会堆积很多而不可读。库就是一款专门控制日志输出的库,能够完美解决我们的上述需求。 NPM酷库,每天两分钟,了解一个流行NPM库。 今天我们要了解的库是debug,一个专门用来控制输出调试日志的库。 通常,我们直接使用 console.log 输出调试日志,使用console对象直接将日志输...

    funnyZhang 评论0 收藏0
  • NPM酷库:jsdom,纯JS实现DOM

    摘要:酷库,每天两分钟,了解一个流行库。昨天认识了一个在环境下操作的库,实现了接口,用起来十分方便。今天,我们要学习的就是一个纯实现的,可以在环境中模拟出环境,像这样对依赖的库就可以在中运行了。 NPM酷库,每天两分钟,了解一个流行NPM库。 昨天认识了一个在Node.js环境下操作HTML的库 cheerio,cheerio实现了jQuery接口,用起来十分方便。为什么不直接用jQuery...

    13651657101 评论0 收藏0
  • NPM酷库:jsdom,纯JS实现DOM

    摘要:酷库,每天两分钟,了解一个流行库。昨天认识了一个在环境下操作的库,实现了接口,用起来十分方便。今天,我们要学习的就是一个纯实现的,可以在环境中模拟出环境,像这样对依赖的库就可以在中运行了。 NPM酷库,每天两分钟,了解一个流行NPM库。 昨天认识了一个在Node.js环境下操作HTML的库 cheerio,cheerio实现了jQuery接口,用起来十分方便。为什么不直接用jQuery...

    tylin 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<