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

IT技术 javascript node.js eval sandbox sanitize
2021-03-14 03:47:36

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

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

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

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

5个回答

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

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 }

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

有没有针对无限循环的保护措施?
2021-04-18 03:47:36
这似乎并不安全,例如:(vm.runInNewContext('this.constructor.constructor("return process")().exit()');来自 vm2 README:github.com/patriksimek/vm2)。
2021-04-23 03:47:36
@Qwertiy 您可以像这样vm.runInNewContext(while (true) 1以毫秒为单位使用超时, {}, {timeout: 1000});
2021-05-14 03:47:36

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

$ npm install vm2

然后:

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

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

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

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

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

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

不要误导,gf3/sandbox 使用子进程和vm module,检查代码。所有沙盒解决方案都是如此。
2021-04-23 03:47:36
警告!gf3/sandbox 1年没更新了,还有一个open issue可以破解沙箱:github.com/gf3/sandbox/issues/29
2021-04-29 03:47:36
我将继续接受,我将在接下来的几天内查看我在上面链接的沙箱和沙堡module。谢谢。
2021-05-05 03:47:36
对于未来的观众,目前 gf3 是可利用的,可以被破解。
2021-05-13 03:47:36

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

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

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

这时候Jailed被破解了:github.com/asvd/jailed/issues/33
2021-05-03 03:47:36
@arve0 你是对的,jailed 在 node 下被破坏了,正在准备修复
2021-05-12 03:47:36
替代方法:github.com/patriksimek/vm2看起来是安全的,但看到日志潜在的突破,我会小心。
2021-05-12 03:47:36

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