繁体   English   中英

如何在具有动态加载、不受信任的模块的应用程序中对代码进行沙箱处理?

[英]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 的代码被正确封装。

不幸的是,这仍然让我不得不以某种方式执行不安全的代码,而且我认为除了使用evalFunction 即使恶意代码无法访问 Node API,它仍然可以完全访问renderer全局 scope,从而使应用程序容易受到例如原型污染攻击。

总结一下:

  1. 执行不受信任代码的更安全的地方显然是在渲染器中
  2. 除了使用evalFunction ,别无选择
  3. 这使得renderer全局 scope 容易受到攻击,我可以尝试缓解但永远无法使其完全安全

我的第一个问题:这些假设是否正确,或者有更好的方法吗?

风险以及如何减轻风险

因此,潜在的恶意代码可以访问renderer全局 scope。 有什么风险?

好吧,任何敏感的用户数据都将安全地存储在preload中,使用 Node API 访问用户计算机也是如此。 攻击者可以破坏游戏(如当前的“会话”),但我可以捕获由此引起的任何错误,并在关闭恶意 mod 的情况下重新加载游戏。 全局 scope 将仅包含必要的构造函数,而没有游戏类的实际实例。 这似乎有点安全,可能发生的最糟糕的事情是重新加载游戏。

我的第二个问题:我在这里是否遗漏了有关风险的任何信息?

我的第三个问题:使用evalFunction是否有任何我没有想到的风险? 自从我开始接触 JS 以来,我有点被“eval bad”轰炸,现在我什至考虑使用它都觉得很脏。 确切地说,我可能会使用new Function代替。

感谢您阅读这篇长文!

对此没有通用的解决方案,因为这在很大程度上取决于项目本身的结构。

您可以尝试使用espree来解析不安全的代码,并且只有在无法访问任何全局变量时才执行它。

但这很可能不会阻止所有攻击,因为您可能认为由于程序的结构方式可能导致的某些其他攻击,不安全代码中的require (或包含/加载其他脚本的任何其他方式)也可能打开允许某些攻击的侧通道。

evalnew Function一般都不错,至少没有以任何不同的方式加载/包含不安全代码那么糟糕。 许多库对生成的代码使用代码评估,这就是这些函数的目的。 但它经常被误用在不需要这样做并且不应该做的事情的情况下。

最安全的方法是最有可能在 WebWorker 中运行代码并为 Mod 定义 API 以在 mod 和应用程序之间进行通信。 但这需要对数据进行序列化和反序列化,当将数据从应用程序传递给 mod 时,反之亦然,这可能会很昂贵(但这就是使用 WebAssmebly 所做的)。 所以我会读一点 WebAssembly 是如何解决通信的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM