在运行不受信任的用户代码时阻止 Node.js 中的系统调用
Posted
技术标签:
【中文标题】在运行不受信任的用户代码时阻止 Node.js 中的系统调用【英文标题】:Prevent system calls in Node.js when running untrusted user code 【发布时间】:2014-03-22 02:41:49 【问题描述】:我目前正在考虑在 node.js 中运行用户提供的代码的问题。我有两个问题:
-
用户脚本不得读取或写入全局状态。为此,我假设我可以简单地产生一个新进程。还有其他考虑吗?我是否必须以某种方式对子进程隐藏父进程,或者子进程无法读取、写入或以其他方式玩弄父进程?
用户脚本不能对系统做任何奇怪的事情。所以,我正在考虑禁止任何系统调用。我如何实现这一目标? (请注意,如果我可以禁止进程模块,那么第 1 点也应该被修复,不是吗?)
【问题讨论】:
你在什么操作系统上运行? 我希望它适用于所有系统(至少 Windows 和 Linux)。 这能回答你的问题吗? How to run untrusted code serverside? @Jerska 据我了解,这些天,vm2
似乎是要走的路
当标记为重复时,这是一条自动消息。vm2
将是运行node
进程的方法,但需要对任何新的node
版本进行仔细维护。如果您希望执行原始 javascript,isolated-vm
将是更好的选择。
【参考方案1】:
您正在寻找来自 vm
模块 (vm documentation) 的 runInNewContext
函数。
当你使用这个函数时,它会创建一个非常有限的上下文。您需要将任何您想要的东西传递到成为全局对象的沙盒对象中。例如:如果您希望不受信任的代码写入控制台,则需要在沙盒对象中包含 console
。
要考虑的另一件事:创建新上下文是一项非常昂贵的操作 - 需要额外的时间和内存来完成。认真考虑你是否绝对需要这个。还要认真考虑这种情况发生的频率。
例子:
var vm = require('vm');
var sandbox =
console: console,
msg: "this is a test",
;
vm.runInNewContext('console.log(msg);', sandbox, 'myfile.vm');
// this is a test
更多需要考虑:您将需要创建一个新进程来运行它。即使它在一个新的上下文中,它仍然在调用它的同一个进程中。因此,恶意用户可以简单地设置一个永无止境的for
循环,使其永远不会退出。您需要弄清楚逻辑以了解何时发生此类事情,以便您可以终止该进程并创建一个新进程。
最后的想法:一个新的上下文没有setTimeout
或setInterval
。您可能想要也可能不想添加这些。但是,如果您在不受信任的代码中创建 setInterval
并且不受信任的代码永远不会停止它,那么它将永远持续下去。你需要想办法结束脚本,可能我还没有研究过。
【讨论】:
谢谢。这非常有帮助。最后一点最近也引起了我的注意,这是将 Node 作为服务器运行时的一个主要问题:脚本很容易杀死整个事情。 Node 是否有标准的“系统工具”来解决这个问题?关于上下文(甚至过程)创建的成本:您是否建议将它们集中起来?例如,Apache 默认只创建一个包含 200 个线程的线程池。我想,类似的策略可能对我的方法有用(如果上下文/进程死亡,则重新启动它们),你怎么看? 老实说,我知道的不够多,无法提供帮助。我正在考虑通过运行不受信任的代码来做类似的事情。然而,由于这些问题,我很快就离开了它,并且没有做足够的研究来确切地找出我确实需要什么。我不希望单个恶意用户在任何时候导致任何其他用户代码出现问题。所以对于我的应用程序,我完全放弃了用户提交代码的想法。以上是关于在运行不受信任的用户代码时阻止 Node.js 中的系统调用的主要内容,如果未能解决你的问题,请参考以下文章
如何对不受信任的用户提交的 JavaScript 内容进行沙箱处理?