NodeJS VM2 沙盒绕过漏洞学习

前言

无。


环境搭建

下载安装NodeJS,新建一个目录并运行命令npm init后下载依赖:

1
npm install vm2@3.6.10

npm提示说该版本的vm2存在高危安全漏洞,但是坚持安装。

vm2

NodeJS沙盒,vm沙盒的优化版本,简单用法如下:

1
2
3
4
5
const {VM, VMScript} = require('vm2');

const script = new VMScript("this;");

console.log((new VM()).run(script));

运行一下,看到此时的this作用域为vm环境下的特殊作用域。

可以在本目录的node_modules文件夹下找到vm2的代码,比如main.js中可以找到VMScript的构造函数:

1
2
3
4
constructor(code, filename) {
this.code = code;
this.filename = filename || 'vm.js';
}

只是简单地把待运行代码保存起来。

也可以找到VM的构造函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const host = {
version: parseInt(process.versions.node.split('.')[0]),
console,
String,
Number,
Buffer,
Boolean,
Array,
Date,
Error,
RangeError,
ReferenceError,
SyntaxError,
TypeError,
RegExp,
Function,
Object,
VMError,
Proxy,
Reflect,
Map,
WeakMap,
Set,
WeakSet,
Promise
};

this._context = vm.createContext();

Reflect.defineProperty(this, '_internal', {
value: vm.runInContext(`(function(require, host) { ${cf} \n})`, this._context, {
filename: `${__dirname}/contextify.js`,
displayErrors: false
}).call(this._context, require, host)
});

根据参考文章,这里将一些沙盒中需要的对象放入host中,创建了沙盒作用域并调用vm的API将contextify.js封装成了一个匿名函数,contextify.js涉及到一些对象代理之类的东西。可以看到global下只挂载了VMError和Buffer两个对象:

1
2
3
4
5
6
7
8
9
10
global.VMError = VMError;
...
const LocalBuffer = global.Buffer = Contextify.readonly(host.Buffer, {
allocUnsafe: function allocUnsafe(size) {
return this.alloc(size);
},
allocUnsafeSlow: function allocUnsafeSlow(size) {
return this.alloc(size);
}
});

readonly一直找到Contextify.object,可以看到Buffer实际上是一个代理对象Proxy:

1
2
3
4
const proxy = new host.Proxy(object, host.Object.assign(base, traps, deepTraps));
Contextify.proxies.set(object, proxy);
Contextified.set(proxy, object);
return proxy;

该代理对象拦截了get、set、construct等等操作,所以这个Buffer对象虽然是从外面传入沙盒的,但是也无法访问其constructor等属性,从而保证了沙盒安全性。

CVE-2019-10761

基于调用栈过大爆栈捕获外部对象。

CVE-2021-23449

基于import未经沙箱,

trick

基于对象代理和异常捕获。


参考

NodeJS VM和VM2沙箱逃逸

vm2实现原理分析


NodeJS VM2 沙盒绕过漏洞学习
http://yoursite.com/2023/02/02/NodeJS-VM2-沙盒绕过漏洞学习/
作者
Aluvion
发布于
2023年2月2日
许可协议