【问题标题】:Isolated execution context in JavaScriptJavaScript 中的隔离执行上下文
【发布时间】:2014-01-27 17:50:18
【问题描述】:

我试图在 JavaScript 中一个空的隔离执行上下文中执行一段代码。在下面的示例中,我正在尝试隔离 isolated 执行范围。我想要做的是在没有全局变量的上下文中执行一个函数。

(function() {
  'use strict';

  var scope = Object.create(null);
  var isolated = function() {
    'use strict';
    console.log(document); // Trying to get undefined
                           // but traces `document`.
  };

  isolated.call(scope);
})();

我认为使全局变量无效很简单,但是太多了!

var isolated = function(window, document, location /* etc */) {
  // ...
};

isolated.call(scope, undefined, undefined, undefined /* etc */);

有没有更好的方法来做到这一点?

【问题讨论】:

标签: javascript scope


【解决方案1】:

在 javascript 本身中没有好的方法可以做到这一点(但请参阅 Gareth Hayes 的回答以了解另一种选择)。

有几个不好的方法。

(function() {
  var scope = Object.create(null);
  var obscurer = {};
  for (var key in this) {
     obscurer[key] = undefined;
  }

  with (obscurer) {
    var isolated = function() {
      'use strict';
      console.log(document);
    };
  }

  isolated.call(scope);
})();

请注意,您实际上会收到一个错误,因为没有定义控制台而不是文档,尽管您可以通过不阻止 obscurer 对象中的“控制台”来解决此问题。您可能会发现您需要的全局变量比您意识到的要多。

您也只是阻止了 enumerable 的 window.properties 属性。如果您发现您也想阻止不可枚举的属性,则必须将它们添加到 obscurer。

当然,使用with意味着你也不能再使用严格模式了,大家都会看不起你..

如果您在节点而不是浏览器中工作,则可以使用更多有趣的选项。

【讨论】:

  • Window.prototype.alert.call(window,1) 绕过了这个沙箱。
  • 我得到“TypeError: window is undefined”,但是是的,我不会真的认为这种方法是安全的。据我所知,如果不解析输入代码,就无法制作安全的沙箱。即使这样,也可能会犯很多错误(例如,人们经常忘记 Function 构造函数允许他们评估代码)。
  • 这是一个 Firefox 特定的向量。
  • 我每晚在 Firefox 的控制台中运行它,所以我不知道是 Firefox 的版本还是控制台使它适合我。我想它强调了一点,如果你真的在寻找安全性,那么需要考虑很多边缘情况。确切地知道弗洛伦特为什么要这样做会很有趣......
  • 它也可以在 Chrome 上运行,实际上是 32.0.1700.72 m。但是,这是我的观点,你错过了一件事,这是一个完全绕过,而如果你使用解析器和白名单,它对攻击的抵抗力要强得多。
【解决方案2】:

使用我的 MentalJS 解析器来隔离环境。然后,您可以通过自定义代码来选择它可以访问的对象/变量。

http://businessinfo.co.uk/labs/MentalJS/MentalJS.html

http://code.google.com/p/mentaljs/

默认情况下它允许访问文档,但您可以阻止这种情况,在此处自定义环境 http://code.google.com/p/mentaljs/source/browse/trunk/MentalJS/javascript/Mental.js#260 然后您可以选择他们是否有权访问数学等。

【讨论】:

    【解决方案3】:

    可以在没有 ECMA6 的情况下使用包含您的受信任需求保护代码的 IIFE 来完成,您可以将不受信任的需求隔离代码注入其中(参见示例)。

    (function(injectedFunction) {
        /* Trusted code, that needs protection from untrusted code access */
        var hostingFuncPrivatePrimitive = "Hello there";
        var hostingFuncPrivateObject = {
            this_is_mine: true
        };
    
        var sharedPrimitive = 'This is shared';
        var sharedObject = {};
    
        // Running the untrusted code:
        injectedFunction(sharedPrimitive, sharedObject);
    
        console.log("sharedObject is: " + JSON.stringify(sharedObject));
        console.log("hostingFuncPrivateObject is: " +
            JSON.stringify(hostingFuncPrivateObject));
    })(
    
    (function(primitiveArg, objArg) {
        /* Untrusted code that needs isolation */
    
        // 1. using primitive (legal)
        console.log('primitiveArg is: ' + primitiveArg);
    
        // 2. Writing value to given objArg (legal):
        objArg.mumu = 'mimi';
    
        // 3. Trying to access host function variables (illegal)
        try {
            console.log('hostingFuncPrivatePrimitive is:' +
                hostingFuncPrivatePrimitive);
            hostingFuncPrivateObject.this_is_mine = false;
        } catch (e) {
            console.log(e);
        }
    })
    
    );
    

    如果你把上面的内容放在 Chrome 的控制台中,你会得到:

        primitiveArg is: This is shared
        VM117:29 ReferenceError: hostingFuncPrivatePrimitive is not defined
                at <anonymous>:26:17
                at <anonymous>:11:5
                at <anonymous>:16:3
        VM117:12 sharedObject is: {"mumu":"mimi"}
        VM117:13 hostingFuncPrivateObject is: {"this_is_mine":true}
    

    P.S.:我知道我迟到了,但也许这对任何人都有帮助。

    【讨论】:

      猜你喜欢
      • 2012-05-09
      • 2015-01-28
      • 1970-01-01
      • 1970-01-01
      • 2018-03-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多