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

Posted

技术标签:

【中文标题】安全沙箱并执行用户提交的 JavaScript?【英文标题】:Safely sandbox and execute user submitted JavaScript? 【发布时间】:2013-07-04 23:49:49 【问题描述】:

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

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

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

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

【问题讨论】:

我认为这是一个错误,但你可以试试 node 'vm' 的东西--nodejs.org/api/vm.html 这是一个有趣的编程游戏概念,我不能相信客户端执行代码。出于这个原因,我想在服务器端进行,因为输出将被序列化并发送到 1 个或多个其他客户端。它看起来像 vm 模块或包装它的东西是我想要的。 @CoryGross 您是否发现了沙堡或沙箱的任何漏洞?我正在构建类似的东西(允许用户提交 js 代码),你的输入会对我有很大帮助:) 这里有一个类似的问题(但较旧)有一个有趣的公认答案(提到一些重要问题):***.com/questions/7446729/… 我对你是如何解决的很感兴趣。我有一个类似的问题:***.com/questions/32773981/… 我使用虚拟机“解决”了它,我仍在测试是否有任何方法可以利用我的解决方案。 【参考方案1】:

您可以通过 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”所指出的,它似乎有缺陷。请看cmets。

【讨论】:

这似乎不安全,例如:vm.runInNewContext('this.constructor.constructor("return process")().exit()');(来自 vm2 README:github.com/patriksimek/vm2)。 是否有针对无限循环的保护措施? @Qwertiy 你可以像这样vm.runInNewContext(while (true) 1, , timeout: 1000);使用毫秒级超时。【参考方案2】:

另一种选择是使用http://github.com/patriksimek/vm2:

$ npm install vm2

然后:

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

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

如其他答案的 cmets 中所述。

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

【讨论】:

【参考方案3】:

此答案已过时,因为 gf3 不提供针对沙盒破坏的保护

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

【讨论】:

我将继续接受,我将在接下来的几天里同时查看沙盒和上面链接到的沙堡模块。谢谢。 不要误导,gf3/sandbox同时使用子进程和vm模块,检查代码。所有沙盒解决方案都这样做。 对于未来的观众,目前 gf3 是可利用的并且可以被破解。 小心! gf3/sandbox 1 年没有更新了,还有一个可以破解沙盒的问题:github.com/gf3/sandbox/issues/29【参考方案4】:

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

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

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

【讨论】:

此时Jailed被破:github.com/asvd/jailed/issues/33 @arve0 你是对的,jailed 在 node 下被攻陷,正在准备修复 Alternative: github.com/patriksimek/vm2 似乎是安全的,但看到日志潜在的突破,我会小心的。【参考方案5】:

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

【讨论】:

以上是关于安全沙箱并执行用户提交的 JavaScript?的主要内容,如果未能解决你的问题,请参考以下文章

用户隐私安全卫士——小程序沙箱

浏览器原理 34 # 安全沙箱

为 Node.js 应用建立一个更安全的沙箱环境

一文彻底搞懂前端沙箱

沙箱是啥

Android安全机制