安全沙箱并执行用户提交的 JavaScript?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17513212/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 08:36:10  来源:igfitidea点击:

Safely sandbox and execute user submitted JavaScript?

javascriptnode.jsevalsandboxsanitize

提问by Cory Gross

I would like to have the ability to let users submit arbitrary JavaScript code, which is then sent to a Node.JS server and safely executed before the output is sent back to multiple clients (as JSON). The evalfunction comes to mind, but I know this has multiple security concerns (the user submitted code would be able to access Node's File API, etc). I have seen some projects like Microsoft Web Sandbox and Google Caja which allow execution of sanitized markup and script (for embedding third-party ads on websites), but it seems that these are client-side tools and I'm not sure if they can be safely used within Node.

我希望能够让用户提交任意 JavaScript 代码,然后将其发送到 Node.JS 服务器并在将输出发送回多个客户端(作为 JSON)之前安全地执行。eval我想到了这个函数,但我知道这有多个安全问题(用户提交的代码将能够访问 Node 的文件 API 等)。我见过一些项目,如 Microsoft Web Sandbox 和 Google Caja,它们允许执行经过消毒的标记和脚本(用于在网站上嵌入第三方广告),但似乎这些是客户端工具,我不确定它们是否可以在 Node.js 中安全使用。

Is there a standard way to sandbox and execute non-trusted JavaScript in Node, getting the output. Is it a mistake to try and do this server-side?

是否有一种标准方法可以在 Node 中沙箱化和执行不受信任的 JavaScript,从而获取输出。尝试在服务器端执行此操作是错误的吗?

EDIT:It's not important that the user be able to leverage the full capabilities of JavaScript, in fact it would be preferable to be able to pick and choose which APIs would be provided to the user code.

编辑:用户能够利用 JavaScript 的全部功能并不重要,事实上,最好能够选择将哪些 API 提供给用户代码。

EDIT:I am going to go ahead and update with what I found. This Sandcastle module (bcoe/sandcastle) seems to aim to do what I have in mind. Not sure how secure it is, but since I this is not for anything too important I think I'll if try it. I'll add my own answer if I'm able to successfully do this.

编辑:我将继续更新我的发现。这个 Sandcastle 模块 ( bcoe/sandcastle) 似乎旨在实现我的想法。不确定它有多安全,但因为我这不是为了任何太重要的事情,我想我会尝试一下。如果我能够成功做到这一点,我会添加我自己的答案。

采纳答案by Ginden

This answer is outdated as gf3 does not provide protection against sandbox breaking

此答案已过时,因为 gf3 不提供防止沙箱破坏的保护

http://gf3.github.io/sandbox/- it uses require('child_process')instead of require('vm').

http://gf3.github.io/sandbox/- 它使用require('child_process')而不是require('vm').

回答by ton

You can use sandbox support in nodejs with vm.runInContext('js code', context), sample in api documentation:

您可以使用 vm.runInContext('js code', context) 在 nodejs 中使用沙箱支持,api 文档中的示例:

https://nodejs.org/api/vm.html#vm_vm_runinthiscontext_code_options

https://nodejs.org/api/vm.html#vm_vm_runinthiscontext_code_options

const util = require('util');
const vm = require('vm');

const sandbox = { globalVar: 1 };
vm.createContext(sandbox);

for (var i = 0; i < 10; ++i) {
    vm.runInContext('globalVar *= 2;', sandbox);
}
console.log(util.inspect(sandbox));

// { globalVar: 1024 }

WARN: As pointed by "s4y" it seems to be flawled. Please look at the comments.

警告:正如“s4y”所指出的那样,它似乎有缺陷。请看评论。

回答by Hiroshi Ichikawa

One alternative would be to use http://github.com/patriksimek/vm2:

一种替代方法是使用http://github.com/patriksimek/vm2

$ npm install vm2

then:

然后:

const {VM} = require('vm2');
const vm = new VM();

vm.run(`1 + 1`);  // => 2

as mentioned in comments of other answers.

如其他答案的评论中所述。

I don't know how secure it is, but it at least claims that it runs untrusted code securely (in its README). And I couldn't find any obvious security issues so far as solutions suggested in other answers here.

我不知道它有多安全,但它至少声称它安全地运行不受信任的代码(在它的自述文件中)。就此处其他答案中建议的解决方案而言,我找不到任何明显的安全问题。

回答by asvd

Under Node.js you may create a sandboxed child process, but you also need to append the code with "use strict";, otherwise it is possible to break the sandbox with arguments.callee.caller.

在 Node.js 下,你可以创建一个沙盒子进程,但你也需要用 附加代码"use strict";,否则有可能用 破坏沙盒arguments.callee.caller

Not sure why you need to send it to the server, because the code may also be executed in a sandboxed web-worker.

不确定为什么需要将其发送到服务器,因为代码也可能在沙盒网络工作者中执行。

Also take a look at my Jailedlibrary which simplifies everything just mentioned for both Node.js and web-browser, and additionally provides an opportunity to export a set of functions into the sandbox.

还可以看看我的Jailed库,它简化了刚才提到的 Node.js 和 web 浏览器的所有内容,另外还提供了将一组函数导出到沙箱中的机会。

回答by P?l Thingb?

Depending on your usage, I'd suggest you also consider protecting your sandbox with a virtual environment like gVisor. You can find some info here.

根据您的使用情况,我建议您还考虑使用 gVisor 等虚拟环境来保护您的沙箱。你可以在这里找到一些信息。