【问题标题】:JavaScript - How to hide global scope from eval'd scriptJavaScript - 如何从 eval 脚本中隐藏全局范围
【发布时间】:2013-05-25 06:35:02
【问题描述】:

我通常认为全局作用域是一个始终可以从任何地方访问的命名空间。我想知道理论上是否可以完全隐藏全局范围。例如,假设我们有一些想要evaluate 的代码(在浏览器的控制台中):

var code = 
  "console.log(this);   " + // access the global object directly
  "console.log(window); " + // access the global object as the window object
  "newGlobalVar = 42;   ";  // implicitly create global object
eval(code);

通过包装eval 调用,thiswindow 可以对code 隐藏:

(function (window) { eval(code); }).call({});

但我无法阻止code 隐式创建全局变量。有可能吗?我不想用这个东西,我只是好奇。

【问题讨论】:

  • 您是否要对eval'd/任意代码进行沙箱处理?如果这是您的目标,还有更好的方法。
  • 不,我只是想从用户代码中屏蔽全局范围。这让我想到了这个问题,它是关于理论的。
  • 那么,在现代浏览器中,理论上你可以freeze window 对象。虽然我从未尝试过。
  • @FabrícioMatté 很有趣。我刚刚在 Safari 5.1.9 中尝试冻结和密封,它适用于一般对象,但不适用于全局对象。
  • @Zorgatone 运行任意不受信任的代码是一项艰巨的任务,我会尽一切努力避免它。但如果你真的需要,这些资源可能会很有用:vm.runInNewContext()(仅限 Node.js)、Aether(沙盒不完整,理想情况下应该在 Web Worker 中运行)和Dr. SES(基于能力的安全性)。

标签: javascript global-variables eval information-hiding


【解决方案1】:

如果您在相当现代的浏览器中运行,您可以通过创建一个函数来阻止window 访问,该函数使用参数隐藏windowself 变量,并在严格模式下运行代码。

var obj = {};

var func = new Function("self", "window", "'use strict';" + code);

func.call(obj, obj, obj);

console.log(obj); // see if there were any attempts to set global variables.

任何访问windowself 的尝试都只会访问我们的obj 对象,而this 的值也将是我们的obj

因为我们处于严格模式,所以不允许使用隐式全局变量。此外,函数的默认 this 值将是 undefined 而不是 window

我认为有一些技巧可以解决这个问题,但这应该涵盖大多数情况。

【讨论】:

  • 看来您仍然可以访问全局变量。 code="return location.href;";code="return console;";code="return top;"; 全部返回结果。
  • @jongo45:是的,您可以访问全局变量,因为它们是全局变量。但是您不能对全局范围进行任何操作。我很确定 OP 试图阻止创建新的全局变量,而不是阻止对所有变量的访问。
  • @squint: 不正确,top.myfunc = "123";允许您在代码运行后执行 console.log(myfunc)。它应该在调用代码之前迭代所有全局变量并使其成为参数。
  • @Rahly:那么top应该添加到函数参数中。但同样,如果 OP 实际上试图阻止所有访问,您只需要阻止所有全局变量。我很确定 OP 试图阻止创建新的全局变量,而不是阻止对所有变量的访问。
  • 正确,但根据发布的代码,您的陈述不准确。我只是指出来
【解决方案2】:

注意:这项工作仍在进行中,部分灵感来自 squint 的代码 sn-p。

function quarantinedFunction(fnText){
    var exceptionKeys=[
        "eval","Object",  //need exceptions for this else error. (ie, 'Exception: redefining eval is deprecated')
        "Number","String","Boolean","RegExp","JSON","Date",
    ];
    var forbiddenKeys=[
        "fn","fnText","forbiddenKeys","exceptionKeys","empty","oForbiddenKeys",
    ];
    var oForbiddenKeys=Object.create(null);
    var empty=Object.create(null);
    Object.freeze(empty);
    forbiddenKeys.forEach(function(key){
        oForbiddenKeys[key]=null;
    });
    [this,self].forEach(function(obj){
        Object.getOwnPropertyNames(obj).forEach(function(key){
            if(!key.match(/^[\$\w]+$/))return;
            oForbiddenKeys[key]=null;
        });
    });
    exceptionKeys.forEach(function(key){
        delete oForbiddenKeys[key];
    });

    if(0){//debugging.
        return function(){
            return Object.keys(oForbiddenKeys);
            return Object.keys(empty);
        };
    }

    fnText=[
        '"use strict";',
        "var "+Object.keys(oForbiddenKeys).join(", ")+";",
        "{",
        fnText,
        "}"
    ].join("\n");

    var fn= (function(){
        with(empty)
        {
            return new Function("self","window",fnText);
        }
    })();

    return function(){
       return fn.call(Object.create(null));      //self,window undefined
       return fn.call(empty,empty,empty);  //self,window are objects w/o properties
    };
}

输出结果(来自 Firefox 暂存器):

quarantinedFunction("return location.href;")();
/*
Exception: location is undefined
*/
quarantinedFunction("someGlobalVar=15;")();
/*
Exception: assignment to undeclared variable someGlobalVar
*/
quarantinedFunction("return 9*9;")();
/*
81
*/
quarantinedFunction("return console;")();
/*
undefined
*/

还有一个jsfiddle 有一些结果。

注意:一些意想不到的结果出现在小提琴中,但在其他工具中没有(即location 变量在从 firefox aurora 查看小提琴时返回页面的 url,但不是在 chrome 上或暂存器 devtool 上 - 可能Firefox 的 __noSuchMethod__ 或类似的“后期绑定”机制的手工制作,导致只有在访问时才添加属性。

【讨论】:

    【解决方案3】:

    你可以在乞求时追加: “变量窗口 = 空” 在你的 eval 字符串中。 同样,对于每个属性,在开始时执行一个附加到您的字符串的 for 循环: for(窗口中的 var p) yourEvalString += "var "+p+"=null;"; 并将其放在一个单独的范围内。

    抱歉,英语不是我的母语,我是新登录 Stack Overflow。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-17
      • 1970-01-01
      • 2015-09-30
      • 1970-01-01
      • 2014-04-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多