想象一个场景,我想连续调用用户提供的 Javascript 代码,如下例所示,其中 getUserResult
是某个用户(不是我自己)编写的函数:
for (var i = 0; i < N; ++i) {
var x = getUserResult(currentState);
updateState(currentState, x);
}
如何在浏览器和/或 Node.js 中执行此类代码,而不存在任何安全风险?
更一般地说,如何执行不允许修改甚至读取当前网页或任何其他全局状态的 Javascript 函数?是否有类似浏览器内“JS 虚拟机”的东西?
JSFiddle 如何确保您不能运行任何恶意代码(至少它可以钓鱼您的登录名,在页面的生命周期内运行机器人,如果不是做更糟糕的事情)?或者它根本不能确保这一点?
最佳答案
经过深思熟虑并在此线程中的其他发帖人的帮助下(非常感谢您的帮助!),我找到了第一组问题的答案。不过,我在这里重写了我的答案,因为它总结了概念,还为您提供了一些实际代码来进行试验。
一般来说,这个问题有两种解决方案:我们要么使用iframe
,要么使用Worker
,将代码运行在一个隔离的环境中,从而无法读写当前页面的信息(这是我的第一个主要安全问题)。
Caja + 闭包
还有更完整的沙盒解决方案,例如 Google Caja,它(默认情况下)也在 iframe
中运行其代码。 Caja 不仅做 sandbox JS,还做 HTML 和 CSS。然而,它确实not seem very actively maintained不再。
更新:自最初发布以来,Caja 已被弃用。 It has been replaced与 Closure Toolkit , 具体来说 Closure Library和 Closure Templates .
WebWorker + 黑名单
由 Juan Garcia 提议,我将使用 web worker API,但这不是完整的故事。尽管工作人员无法直接从托管页面访问任何内容,但仍然存在不少安全风险。 This site lists all built-ins available in a Worker's context .
This JSFiddle演示了一种在 window
的上下文之外运行代码字符串而无需通过服务器的方法,正如评论中所指出的那样,这仍然是不安全的。
我对此进行了扩展,并采用了一种基于黑名单的方法,通过删除以下所有内容来禁用所有外部通信:
worker
WebSocket
XMLHttpRequest
importScripts
Webworker + 白名单
然而,实际上最安全的方法是白名单方法(提到 here ),因为它将在未来保持安全(假设任何白名单全局变量的语义永远不会以它们允许的方式改变更多 在任何 future 版本中访问;这是一个有点合理的假设)。
几年前,我最终在我的浏览器内 WumpusGame 中实现了白名单方法,允许您在玩游戏时编写自己的 AI 脚本。 Source code here .可以看到白名单维护在GuestScriptContext中而 worker 由 HostScriptContext 管理.
GameScriptContext展示了如何使用它。
它有几个特性,包括 guest <->主机通信, guest 可以在主机上执行非特权操作(如果它有安全 token ,甚至可以执行特权操作)等等。
注意:它不能很好地与某些扩展一起使用,因为它们会阻止覆盖全局变量(当我尝试运行它时,它会提示 TEMPORARY
是其中之一)。解决方法是将这些列入白名单,或者弄清楚如何使其与现代浏览器安全功能兼容,或者只是以安全为中心的扩展,如 AdBlock 等。
游戏理论上可以玩here , 但由于上述原因,它似乎在 Chrome 中不起作用(我还没有尝试过其他浏览器)。
更多引用资料:
- The W3Schools web worker tutorial .
- This thread和 this html5rocks tutorial关于如何在没有单独文件的情况下运行
Worker
。
关于javascript - 如何在浏览器中安全地运行用户提供的 Javascript 代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22506026/