在运行不受信任的用户代码时阻止 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 版本进行仔细维护。如果您希望执行原始 javascriptisolated-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 循环,使其永远不会退出。您需要弄清楚逻辑以了解何时发生此类事情,以便您可以终止该进程并创建一个新进程。

最后的想法:一个新的上下文没有setTimeoutsetInterval。您可能想要也可能不想添加这些。但是,如果您在不受信任的代码中创建 setInterval 并且不受信任的代码永远不会停止它,那么它将永远持续下去。你需要想办法结束脚本,可能我还没有研究过。

【讨论】:

谢谢。这非常有帮助。最后一点最近也引起了我的注意,这是将 Node 作为服务器运行时的一个主要问题:脚本很容易杀死整个事情。 Node 是否有标准的“系统工具”来解决这个问题?关于上下文(甚至过程)创建的成本:您是否建议将它们集中起来?例如,Apache 默认只创建一个包含 200 个线程的线程池。我想,类似的策略可能对我的方法有用(如果上下文/进程死亡,则重新启动它们),你怎么看? 老实说,我知道的不够多,无法提供帮助。我正在考虑通过运行不受信任的代码来做类似的事情。然而,由于这些问题,我很快就离开了它,并且没有做足够的研究来确切地找出我确实需要什么。我不希望单个恶意用户在任何时候导致任何其他用户代码出现问题。所以对于我的应用程序,我完全放弃了用户提交代码的想法。

以上是关于在运行不受信任的用户代码时阻止 Node.js 中的系统调用的主要内容,如果未能解决你的问题,请参考以下文章

执行不受信任的代码

如何对不受信任的用户提交的 JavaScript 内容进行沙箱处理?

安全执行不受信任的 Haskell 代码

防止不受信任的 C# 代码启动新线程或黑名单/白名单 API

google chrome使用的插件不受支持怎么办?

运行不受信任的软件?