1

我正在编写一个用 C++ 编写的开源跨平台应用程序,它针对 x86 CPU 上的 Windows、Mac 和 Linux。应用程序生成需要验证的数据流(整数),我的应用程序将根据验证结果执行操作。有多个验证器,我们称之为“模块”,它们可以相互交换。

任何人都可以编写模块并与其他用户共享,所以我的应用程序必须确保恶意编写的模块不会以任何方式伤害用户(也许除了通过高 CPU 使用率,在这种情况下,我的应用程序应该能够在一段时间后杀死模块时间量 - 这可以通过使用代理过程来完成)。此外,数据流正在以高速率(高达 100kB/s)发送。

幸运的是,这些模块中的代码通常是对流中数据的简单算术运算(通常在恒定时间内处理每个传入的整数),它们不需要进行任何系统调用(甚至不需要堆分配)。


我考虑了以下可能性(所有这些可能性都有一些缺点):

  • 基于内核的沙盒

    • 在 Linux 上,我们可以使用安全计算 ( seccomp ),它可以防止进程进行任何系统调用,除了使用已经打开的文件解压缩器进行读取和写入。模块创建者会将他们的模块编写为单个函数,该函数接受输入和输出文件描述符(使用 C 或 C++ 等语言)并将其编译为共享对象,然后分发该共享对象。

      我的应用程序可能会准备输入和输出文件描述符,然后是fork()它自己或exec()代理进程,并且这个子进程使用dlopen()anddlsym()来获取指向不受信任函数的指针。然后在执行不受信任的功能之前,将启用严格的安全计算模式。

      缺点:dlopen()实际运行共享库中的构造函数存在问题。这也必须进行适当的沙盒处理,我想不出办法。另外,当然,这个东西只能在 Linux 上运行。据我所知,没有办法在 Windows 上禁止 WinNT 系统调用,因此在 Windows 上类似的解决方案不会很安全。

  • 应用程序级沙盒

    • [[ 任何形式的应用程序级沙盒意味着我们不能运行任何形式的不受信任的机器代码。不受信任的函数可以覆盖其调用堆栈之外的返回值或数据,从而危及整个应用程序(并有效地获取原始应用程序拥有的任何权限)。]]

    • 使模块使用一种不支持任何系统调用的简单脚本语言——只是纯粹的算术运算,也许还有读取输入流的能力。我的应用程序将包含该语言的解释器。

      缺点:不幸的是我还没有找到这种脚本语言。许多脚本语言具有广泛的功能(例如 Python),而沙箱(例如PyPy 的沙箱)只是过滤 OS 系统调用。我会在我的应用程序中附带大量无用的解释器代码,并且可以说由于解释器中的错误,它比除了简单的计算和控制流指令(基本上是一个不进行任何系统调用的函数)。此外,在 C++(机器代码)和脚本语言之间编组数据通常是一个缓慢的过程。

    • 使用不支持任何系统调用的“安全”编译语言分发模块。我的应用程序将包含该语言的 JIT。
      不需要编组,因为我的应用程序会调用不受信任模块的 JITted 机器代码,因此跨此边界的性能应该很快。由于语言限制和“安全”语言的检查,不受信任的模块现在将无法破坏堆栈、尝试面向返回的编程或执行任何其他恶意操作。WebAssembly 是第一个也是唯一一个想到的语言(如果它可以被称为一种语言)。(据我所知,WebAssembly 似乎为我的用例提供了安全保证,对吧?)

      缺点:WebAssembly 的现有实现似乎都是基于浏览器的,所以我不得不从开源浏览器中窃取一个实现。考虑到我必须将它与所有 JavaScript 和其他浏览器位分离,这看起来确实需要做很多工作。但是,基于 LLVM 的独立 WebAssembly JIT似乎正在开发中。


问题:

在 Windows、Mac 和 Linux 上有效执行不受信任的功能的最佳方法是什么?

现在,我认为脚本语言方式可能是最安全的,并且对于模块编写者来说是最简单的。但是对于更有效的解决方案,WebAssembly 可能更好。我是对的,还是有我没有想到的更好或更简单的解决方案?


(备注:我想这个问题中使用的几对标签以前从未一起见过!)

4

1 回答 1

1

关于 WebAssembly:

不幸的是,目前还没有生产质量的独立实施。我预计将来会出现一些,但还没有发生。

由于历史原因,现有的生产实现都是 JavaScript VM 的一部分。幸运的是,这些虚拟机都没有绑定到浏览器。如果您不介意包含一些未使用的 JS 包袱,您可以按原样嵌入它们(撕掉 JS 会非常困难)。然而,一个问题是这些虚拟机还没有专门为 Wasm 提供嵌入接口。你必须通过JS,这是愚蠢的。

有一个用于 WebAssembly 的 C 和 C++ API的初始设计,它可以直接访问嵌入式 Wasm VM。它意味着是 VM 中立的,即可以由任何现有的 VM 实现(repo 包含 V8 之上的原型实现)。这可能会演变成一个标准,但我不能保证任何时间表。现在它只适合勇敢的人。

于 2018-08-23T17:52:26.363 回答