如何在浏览器中安全地运行用户提供的 Javascript 代码? [英] How to safely run user-supplied Javascript code inside the browser?

查看:42
本文介绍了如何在浏览器中安全地运行用户提供的 Javascript 代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一个场景,我想不断调用用户提供的 Javascript 代码,如下例所示,其中 getUserResult 是某个用户(不是我自己)编写的函数:

Imagine a scenario where I want to continuously invoke user-supplied Javascript code, like in the following example, where getUserResult is a function that some user (not myself) has written:

for (var i = 0; i < N; ++i) {
    var x = getUserResult(currentState);
    updateState(currentState, x);
}

如何在浏览器和/或 Node.js 中执行这种代码,而不会有任何安全风险?

How can I execute that kind of code in a browser and/or Node.js, without any security risks?

更一般地说,我如何执行一个不允许修改甚至读取当前网页或任何其他全局状态的 Javascript 函数?有没有类似浏览器内的JS 虚拟机"?

More generally, how can I execute a Javascript function that is not allowed to modify or even read the current webpage or any other global state? Is there something like an in-browser "JS virtual machine"?

JSFiddle 如何确保您不能运行任何恶意代码(至少它可以钓鱼您的登录名,在页面的整个生命周期内运行机器人,如果不是做更糟糕的事情)?还是根本就不能保证?

How does JSFiddle ensure that you cannot run any malicious code (at the very least it could phish your login name, run a bot for the lifetime of the page, if not do much worse things)? Or doesn't it ensure that at all?

推荐答案

经过深思熟虑并在此线程中其他海报的帮助下(非常感谢您的帮助!),我找到了我的第一批答案问题.不过,我在这里重写了我的答案,因为它总结了概念,并为您提供了一些实际的代码供您试验.

After much consideration and with the help of other posters in this thread (thank you so much for your help!), I found a first bunch of answers to my questions. I am re-writing my answer here though, because it summarizes the concepts and also gives you some actual code to experiment with.

一般来说,这个问题有两种解决方案:我们可以使用iframe或者Worker在隔离的环境中运行代码,这样就无法读写当前页面的信息(这是我的第一个主要安全问题).

Generally, there are two solutions to this problem: We can either use iframe or Worker to run code in an isolated environment, thus making it impossible to read or write the current page's information (which is my first major security concern).

有更完整的沙盒解决方案,例如 Google Caja,它(默认情况下)也在 iframe 中运行其代码.Caja 不仅会沙箱 JS,还会沙箱 HTML 和 CSS.但是,它确实似乎不再积极维护.

There are more complete sandbox solutions such as Google Caja, which (by default) also runs its code in an iframe. Caja does not only sandbox JS, but also HTML and CSS. However, it does not seem very actively maintained anymore.

更新:自最初发布以来,Caja 已被弃用.它已被替换闭包工具包,特别是闭包库闭包模板.

Update: Caja has been deprecated since the original posting. It has been replaced with the Closure Toolkit, specifically Closure Library and Closure Templates.

正如 Juan Garcia 所提议的,我将使用 Web Worker API,但这不是完整的故事.尽管工作人员无法直接从托管页面访问任何内容,但仍然存在不少安全风险.此站点列出了 Worker 上下文中可用的所有内置程序.

As proposed by Juan Garcia, I am going with the web worker API, but that is not the complete story. Even though, the worker cannot directly access anything from the hosting page, there are still quite a few security risks. This site lists all built-ins available in a Worker's context.

这个 JSFiddle 演示了一种在窗口外运行代码字符串的方法 的上下文而无需通过服务器,这仍然是不安全的,正如评论中所指出的.

This JSFiddle demonstrates a way to run a string of code outside the window's context without having to go through the server, which is still unsafe, as pointed out in the comments.

我对此进行了扩展,并采用了基于黑名单的方法,通过删除以下所有内容来禁用所有外部通信:

I have extended on that and employed a black-list based approach to disable all outside communication by taking away all of the following:

  • 工人
  • WebSocket
  • XMLHttpRequest
  • importScripts

然而,实际上最安全的方法是白名单方法,(在此处提及),因为它将在未来保持安全(考虑到任何列入白名单的全局变量的语义永远不会以这样的方式改变,即它们允许在任何未来版本中更多访问;这是有点合理的假设).

The actually safest approach however, is a white-list approach, (mentioned here), as it will stay safe into the future (given that the semantics of any whitelisted globals will never change in such a way that they allow more access in any future release; which is a somewhat reasonable assumption).

几年前,我最终在我的浏览器 WumpusGame 中实施了白名单方法,该方法允许您在玩游戏时编写自己的 AI 脚本.源代码在此.您可以看到白名单维护在 GuestScriptContext而 worker 由 HostScriptContext 管理.

I ended up implementing the whitelist approach in my in-browser WumpusGame that allows you to write your own AI script while playing the game, a few years back. Source code here. You can see that the Whitelist is maintained in GuestScriptContext while the workers are managed by the HostScriptContext.

GameScriptContext 展示了如何使用

它有几个特性,包括来宾<->主机通信,来宾可以在主机上执行非特权操作(如果它有安全令牌,甚至是特权操作)等等.

It has several features, including guest<->host communication, guest can execute non-privileged actions (and if it has a security token even privileged actions) on the host, and a lot more.

注意:它不适用于某些扩展,因为它们会阻止覆盖全局变量(当我尝试运行它时,它抱怨 TEMPORARY 是其中之一).解决方法是将它们列入白名单,或者弄清楚如何使其与现代浏览器安全功能配合使用,或者仅使用以安全为中心的扩展程序,例如 AdBlock 等.

NOTE: It does not play well with some extensions, as they will prevent overriding globals (when I try to run it, it complains about TEMPORARY being one of them). The fix would be to either whitelist those, or figure out how to make it play nice with modern browser security features, or just security-focused extensions, such as AdBlock etc.

游戏理论上可以玩这里,但由于上述原因,它似乎无法在Chrome(我还没有尝试过其他浏览器).

The game is theoretically playable here, but because of reasons above it does not seem to work in Chrome (and I haven't tried other browsers yet).

更多参考:

  • The W3Schools web worker tutorial.
  • This thread and this html5rocks tutorial on how to run a Worker without separate files.

这篇关于如何在浏览器中安全地运行用户提供的 Javascript 代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆