[英]How can I sandbox code in an application with dynamically loaded, untrusted modules?
我正在 Electron 中制作游戏,我希望它支持模组。 有时这些模组需要使用自定义逻辑,这给我留下了动态加载代码的问题,我发现很难想出一种安全的方法。
理想情况下,我想执行 mod 脚本,同时只传递他们需要的几个安全游戏对象作为参数,但这似乎是不可能的(无论解决方案如何,该代码仍然可以访问全局范围)。
最重要的是,我必须防止不受信任的代码访问preload
全局 scope(使用节点 API),因此预加载中的require
或其他任何操作都在preload
之外。
因此,该代码必须在renderer
中执行。
我可以使用fs
读取preload
中的文件,也可以使用fetch
直接在renderer
中读取文件。 我将nodeIntegration
设置为false
并将contextIsolation
设置为true
,并且preload
脚本加载的受信任代码通过contextBridge
有选择地传递给renderer
。 访问 Node API 的代码被正确封装。
不幸的是,这仍然让我不得不以某种方式执行不安全的代码,而且我认为除了使用eval
或Function
。 即使恶意代码无法访问 Node API,它仍然可以完全访问renderer
全局 scope,从而使应用程序容易受到例如原型污染攻击。
总结一下:
eval
或Function
,别无选择renderer
全局 scope 容易受到攻击,我可以尝试缓解但永远无法使其完全安全我的第一个问题:这些假设是否正确,或者有更好的方法吗?
因此,潜在的恶意代码可以访问renderer
全局 scope。 有什么风险?
好吧,任何敏感的用户数据都将安全地存储在preload
中,使用 Node API 访问用户计算机也是如此。 攻击者可以破坏游戏(如当前的“会话”),但我可以捕获由此引起的任何错误,并在关闭恶意 mod 的情况下重新加载游戏。 全局 scope 将仅包含必要的构造函数,而没有游戏类的实际实例。 这似乎有点安全,可能发生的最糟糕的事情是重新加载游戏。
我的第二个问题:我在这里是否遗漏了有关风险的任何信息?
我的第三个问题:使用eval
或Function
是否有任何我没有想到的风险? 自从我开始接触 JS 以来,我有点被“eval bad”轰炸,现在我什至考虑使用它都觉得很脏。 确切地说,我可能会使用new Function
代替。
感谢您阅读这篇长文!
对此没有通用的解决方案,因为这在很大程度上取决于项目本身的结构。
您可以尝试使用espree来解析不安全的代码,并且只有在无法访问任何全局变量时才执行它。
但这很可能不会阻止所有攻击,因为您可能认为由于程序的结构方式可能导致的某些其他攻击,不安全代码中的require
(或包含/加载其他脚本的任何其他方式)也可能打开允许某些攻击的侧通道。
eval
和new Function
一般都不错,至少没有以任何不同的方式加载/包含不安全代码那么糟糕。 许多库对生成的代码使用代码评估,这就是这些函数的目的。 但它经常被误用在不需要这样做并且不应该做的事情的情况下。
最安全的方法是最有可能在 WebWorker 中运行代码并为 Mod 定义 API 以在 mod 和应用程序之间进行通信。 但这需要对数据进行序列化和反序列化,当将数据从应用程序传递给 mod 时,反之亦然,这可能会很昂贵(但这就是使用 WebAssmebly 所做的)。 所以我会读一点 WebAssembly 是如何解决通信的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.