JavaScript沙箱:在给定范围内隐藏全局变量

JavaScript sandboxing: hide global variables from a given scope

本文关键字:范围内 隐藏 全局变量 沙箱 JavaScript      更新时间:2023-09-26

我想创建一个HTML+JS环境,用户可以在其中输入并运行任意JavaScript代码,这将在给定jail对象的上下文中执行。我已经建立了一个游乐场来说明我到目前为止所知道的。

这个做得还不错:

  • 基本评价工作:
    • 输入:2 + 2
    • 输出:4
  • this返回jail对象
    • 输入:this
    • 输出:[object Object]
  • this.hello()运行期望的方法
    • 输入:this.hello()
    • 输出:hello world!
  • 用户可以设置自己的函数并稍后执行:
    • 输入:this.foo = function() { return 42; }
    • 输出:function () { return 42; }
  • 输入:this.foo()
  • 输出:42
  • 试图访问一些对象,我想保持"隐藏"从监狱上下文失败:
    • 输入:hidden
    • 输出:ReferenceError: hidden is not defined
  • 但是,它完全不能隐藏全局可访问的属性,如windowdocument for user:

    • 输入:window
    • 电流输出:[object Window]
    • 期望输出:ReferenceError: window is not defined

    到目前为止,我想到的最好的解决方案是在Jail对象声明中使用undefinednull填充我能想到的所有全局变量,如更新版本所示。这样,它们似乎永远消失在监狱的范围内,用户将无法访问它们。我的问题:

      我说的对吗?这足够安全吗?
    • 是否有更好的方法,即真的在某些范围内不定义全局的东西,而不是用一些占位符值重写它们?

    如果它是客户端,你可以保证使用现代浏览器,使用web worker代替;它们更安全,你还可以阻止无限循环占用主线程,并通过调用Worker#terminate实现超时。

    为每次执行启动一个新的worker:

    var worker = new Worker('path/to/evaluator.js');
    

    从worker接收消息:

    worker.onmessage = function (e) {
        console.log(e.data);
    };
    

    发送执行代码:

    worker.postMessage(someCode);
    

    在worker中,听:

    onmessage = function (e) {
        postMessage(eval(e.data));
    };
    

    并且确保在收到消息后也调用terminate,因为worker可以自己调用postMessage。(你可以避免这种情况,但这真的没有意义。)

    Web worker不能访问主执行上下文中的任何内容,它们在另一个线程上运行,并且由浏览器实现,因此它们比典型的delete-dangerous-things沙盒要安全得多。

    然而,

    他们可以访问XMLHttpRequest;看它是可能的沙盒JavaScript运行在浏览器中?