Javascript 如何在具有动态加载的、不受信任的模块的应用程序中对代码进行沙箱处理?
我正在用Electron做一个游戏,我希望它支持mods。有时那些mod需要使用自定义逻辑,这就给我留下了动态加载代码的问题,我发现很难找到一种安全的方法 我所考虑的 理想情况下,我希望在执行mod脚本的同时,只传递它们所需的几个安全游戏对象作为参数,但这似乎是不可能的(无论采用何种解决方案,该代码仍然可以访问全局范围) 最重要的是,我必须防止不受信任的代码访问Javascript 如何在具有动态加载的、不受信任的模块的应用程序中对代码进行沙箱处理?,javascript,node.js,electron,Javascript,Node.js,Electron,我正在用Electron做一个游戏,我希望它支持mods。有时那些mod需要使用自定义逻辑,这就给我留下了动态加载代码的问题,我发现很难找到一种安全的方法 我所考虑的 理想情况下,我希望在执行mod脚本的同时,只传递它们所需的几个安全游戏对象作为参数,但这似乎是不可能的(无论采用何种解决方案,该代码仍然可以访问全局范围) 最重要的是,我必须防止不受信任的代码访问preload全局范围(使用节点API),因此require或在preload中执行的任何其他操作都不在窗口中 因此,必须在渲染器中执行
preload
全局范围(使用节点API),因此require
或在preload
中执行的任何其他操作都不在窗口中
因此,必须在渲染器中执行该代码
到目前为止我的解决方案
我可以使用fs
在preload
中读取文件,也可以使用fetch
直接在渲染器中读取文件。我将nodeIntegration
设置为false
和contextIsolation
设置为true
,并且通过contextBridge
有选择地将preload
脚本加载的可信代码传递给渲染器。访问节点API的代码已正确封装
不幸的是,这仍然让我不得不以某种方式执行不安全的代码,我认为除了使用eval
或函数
之外,没有其他方法。即使恶意代码无法访问节点API,它仍然可以完全访问渲染器
全局范围,使应用程序容易受到原型污染攻击等攻击
总而言之:
执行不受信任代码的更安全的地方显然是在渲染器中
除了使用eval
或函数
这使得渲染器
全局范围容易受到攻击,我可以尝试减轻这些攻击,但无法使其完全安全
我的第一个问题:这些假设是真的,还是有更好的方法
风险以及如何减轻风险
因此,潜在的恶意代码可以访问呈现程序
全局范围。有什么风险
那么,任何敏感的用户数据都将安全地存储在预加载
,使用节点API访问用户的计算机也是如此。攻击者可以破坏游戏(如当前“会话”),但我可以捕获由此导致的任何错误,并在关闭恶意mod的情况下重新加载游戏。全局范围将只包含必要的构造函数,而不包含游戏类的实际实例。看起来有点安全,最糟糕的事情可能是重新加载游戏
我的第二个问题:我是否遗漏了关于风险的任何信息?
我的第三个问题:使用eval
或Function
是否存在我没有想到的风险?自从我开始进入JS以来,我就一直被“eval bad”轰炸,现在我甚至考虑使用它都觉得很肮脏。确切地说,我可能会使用新函数
感谢您阅读这篇长篇文章 没有通用的解决方案,因为这在很大程度上取决于项目本身的结构
您可以尝试使用它来解析不安全的代码,并且仅在无法访问任何全局变量时执行它
但这很可能不会阻止所有攻击,因为您可能认为,由于程序的结构方式,需要
(或包含/加载其他脚本的任何其他方式)在该不安全代码中也可能会打开允许某些攻击的侧通道
eval
和new Function
通常都不错,至少没有加载/以任何不同方式包含不安全代码那么糟糕。许多库对生成的代码使用代码求值,这就是这些函数的目的。但它经常被误用在不需要这样做的情况下,而这是不应该做的事情
最安全的方法是在WebWorker中运行代码,并为mod定义API,以便mod和应用程序之间进行通信。但这需要对数据进行序列化和反序列化,当从应用程序向mod传递数据时,反过来,这可能会很昂贵(但这就是WebAssmebly所做的)。所以我会读一点关于WebAssembly如何解决通信的内容