我试图在沙箱模块在linux + node.js中运行不受信任的JavaScript代码,但它已经坏掉了,我需要的只是让用户编写打印输出文本的JavaScript程序。 没有其他I / O是允许的,只是简单的JavaScript将被使用,没有其他节点模块。 如果这不是真的可以做的话,那么对于这样的任务,你还会提出什么其他的语言? 我需要的最小特征是一些math,正则expression式,string操作和基本的JSON函数。 假设脚本运行5秒钟,然后进程就会被终止,我该怎么做呢?
我最近创建了一个用于对不可信代码进行沙盒处理的库,它似乎符合要求(在Node.js中执行受限进程中的代码,以及用于Web浏览器的沙箱化iframe中的Worker中):
https://github.com/asvd/jailed
有机会从主应用程序导出给定的一套方法到沙盒,从而提供任何自定义API和特权组(这个功能实际上是我决定从头开始创建一个库的原因)。 所提到的数学,正则表达式和字符串相关的东西是由JavaScript本身提供的,任何额外的东西都可以从外部显式地导出(就像一些与主应用程序通信的函数)。
沙盒的基本思想是,你需要变量预先定义为全局变量,所以如果你通过取消它们或者用受控变量来替代它们,那么它就不能逃脱。 只要你不忘记什么。
首先替换拒绝require()或用受控的东西替换它。 不要忘记进程和“全球”aka“根”,困难的事情是不要忘记任何东西,这就是为什么它依靠其他人已经建立了一个沙箱;-)
问自己这些问题:
正如你对沙箱模块的实验已经知道的那样,编写你自己的沙盒并不是微不足道的。 沙盒的主要问题是你必须把事情做好。 一个错误将完全破坏你的安全,这就是为什么浏览器开发者与全球各地的破解者不断战斗的原因。
也就是说,简单的沙箱很容易做到。 首先,你需要编写你自己的JavaScript解释器,因为你不能使用node.js中的一个,因为eval()
和require()
(两者都会让crackers逃离沙箱)。
解释器必须确保解释的代码除了你提供的几个全局符号之外不能访问任何东西。 这意味着不能有一个eval()
函数,例如(或者你必须确保这个函数只在你自己的JavaScript解释器的上下文中被评估)。
这种方法的缺点:很多工作,如果你的口译员犯了一个错误,饼干可以离开沙箱。
另一种方法是清理代码并使用node.js的eval()
运行它。 您可以通过运行一堆正则表达式来清理已有的代码,例如/eval\s*[(]//g
来移除恶意代码部分。
这种方法的缺点:很容易犯一个错误,会让你容易受到攻击。 例如,regexp和node.js被认为是“空白”之间可能不匹配。 解释器可能会接受一些模糊的unicode空白,但不能通过正则表达式来允许攻击者运行eval()
。
我的建议:写一个小的演示测试用例,说明沙箱模块是如何破碎的,并修复它。 它会为你节省大量的时间和精力,如果沙箱里有一个bug,那不会是你的错(至少不是)。
如果你能够承受性能的影响,你可以运行JS在一个一次性的虚拟机与适当的CPU和内存限制。
当然,那么你相信VM解决方案的安全性。 通过与一个普通的JS沙盒一起使用,你会有两层安全。
对于其他图层,将沙箱放在与主应用程序不同的物理机器上。
Docker.io是一个真棒新的孩子,使用LXC和CGroups来创建沙箱。
这里是一个使用Docker和Go Lang的在线主要实现(类似于codepad.org )
这只是为了证明可以安全地运行Docker Containers中的许多编程语言编写的不可信代码 ,包括node.js
我现在正面临着类似的问题,而且我只阅读关于沙箱模块的坏消息。
如果您不需要特定于节点环境的任何东西,我最好的方法是使用PhantomJS或Chimera等无头浏览器作为沙盒环境。
知道它迟到回答这个问题,猜测下面的工具可能是上面的答案/评论中没有提到的增值。
试图实施类似的用例。 通过网络资源后, https ://www.npmjs.com/package/vm2似乎正在处理沙箱环境(nodejs)相当好。
这几乎满足了沙箱功能,如限制内置或外部模块的访问,沙箱之间的数据交换等。