是否可以通过覆盖各种函数(例如
alert
、window.location
和eval
)来沙箱用户提交的Javascript?
我并不是在寻找完美的解决方案。我确信有些人仍然会找到一种方法来重新排列 div 以拼写出脏话或恶意内容,但如果我可以 100% 可靠地禁用页面重定向,我会非常高兴。
我在 Chrome 中尝试过,并做了类似的事情
context={}; //use this to prevent `this` from being `window`
context.f=function(){
var window=null,location=null,eval=function(){};
console.log(window); //also the other two
};
context.f();
看起来很有希望。如果我用用户提交的代码替换
console
行(检查括号平衡),这会是一个荒谬的坏主意还是一个有点坏的主意?在 Chrome 上,我仍然可以通过 this
到 Function 并重新定义事物来破坏事物,但这对我来说是可以接受的。
您可以使用 Microsoft Web Sandbox 或 Google Caja。
这里还有两个可能的解决方案(免责声明:我自己刚刚开始寻找,所以我不是专家)。
这非常有趣,使用网络工作者来沙箱不受信任的代码:
https://github.com/eligrey/jsandbox
尽管如此,我想知道这是否还会得到维护,或者以下 html5“沙箱”iframe 属性是否会取代它:
vm.js是一个用纯coffescript实现的javascript虚拟机(应该在相对较旧的浏览器中运行),可以用作轻量级的进程内沙箱。它可以打破无限循环并保护全局对象免受修改。
根据需要执行的操作,您始终可以在无文档上下文的环境中运行 JavaScript,例如通过 Rhino,然后获取服务器端的结果并清理/插入这些结果。
您也可以尝试 Douglas Crockford 的 AdSafe,尽管它确实限制了 JavaScript 的可能性。
用局部变量屏蔽全局变量实际上并不安全。使用 Google Caja 等工具预处理不受信任的代码可能会有所帮助,但这不是必需的:
对于网络浏览器来说,只需在 Worker 中运行代码就足够了 - 如今它似乎受到很大限制。 请参阅下面的更新
对于 Node.js,您可以在沙盒进程中 fork() 并执行其中的代码(使用 child_process 模块)。
还有一些用于简化沙箱的库,其中一个由我自己创建的库是Jailed(还有一个带有JS-Console的demo,它在沙箱中执行用户提交的代码)。
更新:显然我错了,worker 本身并不安全,因为它可以访问一些同源的东西,例如 IndexedDB。我已经提交了相关问题。解决方案是另外将工作人员放入 sasndboxed iframe 中,这也在我的 Jailed 库中实现。
使用 HTML5“沙盒”iframe 属性。
我为此编写了一个 JavaScript 函数。
function evalUnsafe(userCode) {
var vars = [];
var legal = {console: 'console', alert: 'alert'};
for(var b in this) {
if (!(b in legal)) {
vars.push(b);
}
}
var funcs = vars.join(",");
var code = "(function sandbox(" + funcs + ") {function runthis() {eval(" + JSON.stringify(userCode) + ");};var a = new runthis();})();";
eval(code);
}
然后你就可以这样做
示例1:
evalUnsafe("alert(window);");
示例 2(来自 php 文件):
evalUnsafe(<?php echo json_encode(file_get_contents("example.js"));?>);
您可以从这里下载:
JS-Interpreter 是一种通过创建“自己的虚拟机,除了开发人员提供的之外没有外部 API”来沙箱代码的方法。它基于 Marijn Haverbeke 的Acorn。然而,这个解决方案相当慢(根据文档是 200 倍)。