有没有办法在node.js中限制子进程对我的系统的访问?

时间:2018-08-15 04:48:33

标签: node.js

我正在尝试以execute的不同语言为node程序构建服务,并提供输出。到目前为止,我使用child_process的{​​{1}}来生成命令。

spawn

有没有一种方法可以限制对此let p = spawn('python',[sourceFilePath]); 的访问,使其不能访问child_processnetwork等?

3 个答案:

答案 0 :(得分:3)

如果是Unix,则可以提供uid,即具有较低权限的用户/组的gid:

var child = spawn(process, args, {
    detached: true,
    uid: uid, 
    gid: gid, 
    cwd: appDir,
    stdio: [ 'ignore', 'pipe', 'pipe']
})

答案 1 :(得分:2)

Node.js本身不提供任何机制来将子进程限制为仅可用资源的子集,而不能设置子进程的UID / GID,这对于您的目标而言可能是不够的。

请注意,将远程代码作为商业模型(即各种 * fiddle.org ,在线游乐场等)执行非常困难,因为保护主机运行是一项艰巨的任务系统。

  

我将假定您的程序最终将在Linux服务器上运行,因为这是当今可用于Node.js部署的最常见的服务器类型。涵盖所有类型的操作系统的此主题可能太宽泛,可能没有帮助。

您的目标

  • 使用用户提供的输入执行程序,然后将输出返回给用户
  • 限制该程序访问某些或所有I / O资源(文件系统,网络,主机OS信息,内存等)
  • 容忍恶意用户企图破坏/提取信息/破坏您的服务器等。

Node.js根本对这里没有帮助。 Node可以产生一个子进程,仅此而已。它不控制任何这些I / O资源。 内核执行。我们必须研究Linux内核在这一领域提供的功能。

我找到了very detailed article about Linux sandboxing,我将以此为灵感。如果您有兴趣,我建议您阅读并搜索相似的内容。

低级:Linux名称空间

Linux内核提供了低级的机制来隔离各种系统资源中的进程。尽管我认为这对于您的用例来说太低了,但是您可能仍要检查一下它们。

Firejail

Firejail是一种工具,可将用于测试目的的进程与其他系统资源隔离开。我从未使用过它,但是看起来它可以用于您的用例。

容器(即Docker)

容器通常利用Linux命名空间来创建一个环境,即使它们允许与主机OS完全隔离,该环境对于在其中运行的进程来说似乎是一个完整的操作系统。在容器内运行程序时,可以限制网络访问,文件系统访问甚至CPU /内存使用。

考虑到您的用例,我可能会采用容器隔离,因为当今围绕它们的社区非常庞大,这增加了您找到正确的支持/文档​​以实现目标的可能性。

答案 2 :(得分:1)

您可以为此使用vm2模块。我也可以使用它来运行用户不受信任的代码。您可以创建沙箱来运行用户代码,并且沙箱可以访问您仅为其指定的资源。 例如

    const vm = new VM({
                                            sandbox: {
                                                    console:console,
                                                    timeout:200,
                                                    fileName:fileName,
                                                    cmdCommand:cmdCommand,
                                                    url:url,
                                                    exec:exec,
                                                    input:inputs,
                                                    imageName:imageName,
                                                    reqs:reqs,
                                                    resp:resp}
                                            });

这可以是您的沙箱,用户只能使用上面列出的特定变量,例如,如果您从上方删除控制台,则用户将无法登录,如果他们尝试执行该代码将出错。


vmCode = `var child = exec(cmdCommand,function(stderr, result) {
                    console.log("done in exec")
                    console.log(fileName)
                    console.log(result)

                    if(stderr){
                console.log("stderr")
                console.log(stderr)
                resp.send({"error":"Syntax error"})
                }
                else {
                    console.log(result)
                    }
                   }
            })`

在这里将定义您的子流程代码(作为字符串)

最后


vm.run(vmCode,(err)=>{
            console.log("done")
        })

此语句将执行字符串形式的代码(上面定义了vmCode)

在文档中写道,您可以使用它来运行不受信任的代码。 要了解更多信息,请点击此处https://www.npmjs.com/package/vm2