Graphene-ng简介:在SGX飞地中运行任意有效载荷

客座作者: 乔安娜·鲁特科夫斯卡 (Invisible Things Lab)

几个月前,在我在Black Hat Europe上的主题演讲中,我讨论了在构建计算机系统时应如何限制信任量。 最近,英特尔的一项新技术在开发人员和研究人员中都越来越流行,该技术有望朝着使信任度最小的系统迈出一大步。 我说的当然是英特尔SGX。

大约5年前,英特尔SGX首次引起了我的注意,这是在英特尔正式将有关它的信息添加到官方软件开发人员手册之前的一段时间。 我已经写了两篇关于这种(当时即将到来的)技术的想法的文章,这些文章既包含积极感,也包含消极感。

在过去的两年左右的时间里,我们与我在ITL的团队一起对这种引人入胜的技术进行了更深入的研究。 今天,我想分享一些有趣的项目的介绍性信息,我们已经与Golem的朋友们一起进行了几个月的研究。

最近,术语“基于安全区”的计算已越来越多地用于描述一种安全容器的形式,该安全容器允许进行不受主机保护的计算,例如外部操作系统,虚拟机管理程序,甚至来自底层固件的干扰例如BIOS / SMM / UEFI。

自然,这与当今使用的安全容器(并由各种VM,Linux / Docker容器等实现)的通常定义形成了鲜明的对比,这意味着保护主机不受容器中运行的任何代码的侵害。 。 换句话说:飞地和容器代表两个不同的互补目标,通常可以预见两者将同时部署。

人们一直在思考如何保护在可能受到威胁的主机上运行的代码和数据,这不足为奇。

甚至我早在2011年就写了一篇文章,讨论了如何利用Intel TXT技术(可以认为是Intel SGX的逻辑前身)在不可信的云中以某种方式实现可信执行。 Private Core(现在为Facebook)也进行了非常有趣的工作,从2012年开始,持续了几年,不幸的是从未公开发布(?)。 但是基于英特尔TXT的解决方案笨拙,容易受到一些基本问题的困扰,例如SMM攻击。

今天,英特尔SGX似乎是一个非常有前途的候选人(到目前为止是唯一的候选人?),它为基于安全区域的计算提供了一个相当好的解决方案。

但是,英特尔不仅是唯一的技术,还有其他技术,而AMD安全加密虚拟化(SEV)是另一种有趣的技术。 不幸的是,AMD SEV虽然乍看之下非常有前景,但确实存在严重的安全漏洞,例如缺乏对第二级页表的完整性保护,并且通常认为它不能提供针对恶意虚拟机管理程序的保护,而只能提供针对意外事件的保护。虚拟机管理程序漏洞。 希望将来AMD将改善SEV的设计和实施。

还尝试通过通常使用Trust Zone技术在基于ARM的系统上创建所谓的受信任执行环境(TEE),该技术可能类似于基于安全区的计算的思想,因为有效载荷应受到保护,免受主机攻击操作系统。 但是,从体系结构的角度来看,这些对我而言似乎完全不同,因为在Trust Zone的情况下,我们实际上是在讨论经典的“通过隔离模型进行安全性”,只是在虚拟机管理程序将堆栈下移了一层的情况下。 从用户和开发人员的角度来看,相似性可能更为显着。 由于不是ARM系统方面的专家,因此我有可能错过一些关键的创新,这使这些解决方案也更类似于Intel SGX和AMD SEV。

英特尔SGX是一项硬件扩展,这意味着人们需要拥有一个相当现代的英特尔处理器才能使用它。 通常,对于大多数基于最新Intel处理器的现代笔记本电脑来说,这应该不是问题。

但是拥有支持SGX的硬件只是故事的一半,因为还需要专门设计的软件来利用SGX提供的功能。 英特尔确实为此提供了一个SDK。

那么,如何将一个应用程序移植到SGX区域内即可使用? 事实证明,这并非易事……

移植应用程序使其在SGX容器中运行并非易事,因为英特尔已将SGX视为仅对应用程序代码和数据的一小部分进行保护的技术。 主要示例包括仅保护密码(密钥生成,签名和解密操作),同时使整个应用程序的其余部分不受来自主机OS的攻击。

这种想法在行业中并不是全新的,因为供应商认为对密钥 (通常属于卖方,例如银行交易的签名密钥或受DRM保护的材料的解密密钥)的保护是主要的关注,而不太强调对实际用户数据(例如,用户电子邮件的内容)的保护。

但是,SGX还有更多问题。

首先,英特尔SGX拥有自己的远程证明方案,奇怪的是,它需要使用由英特尔运营的服务器,即所谓的英特尔证明服务(IAS),以验证证明的证据。 该证明凭证称为:“ quote”,它与基于“ TPM”的“经典”远程证明中使用的名称相同,尽管SGX的“ quote”有些不同。 英特尔决定对其进行加密(不只是签名),而实际上仅将验证仅限于英特尔操作的服务器,这似乎是有问题的。 它不仅会给基于SGX的任何基础架构带来单点故障,而且还使Intel能够为特定用户隐瞒欺骗性证明结果,从而促进选择性的,可合理化的后门程序(请注意,Intel始终可以构建后门程序,只是很难选择性地使用硅内部的通用后门,而且肯定也不合理。

SGX的另一个问题是要求所有SGX飞地都必须使用受英特尔支持的供应商的签名密钥进行签名。 换句话说,在未与Intel签订合法合同的情况下,无法加载SGX区域(以调试模式除外)。 据信,这样做的理由是为了防止飞地内的黑盒恶意软件,这是我(从理论上)在SGX早期描述的东西……

(顺便说一句,在SDM手册中,英特尔描述了一个特殊的MSR寄存器,该寄存器可用于提供自定义的散列,即所谓的启动安全区,似乎可以绕开这一要求,让安全区仅由受英特尔保护的签名遗憾的是,人们坚信,当人们决定使用自定义的发射区时,远程认证将不再起作用,整个技术几乎变得无用了……)

SGX还存在一些实现级别的问题,出于完整性考虑,在此应予以提及。 其中之一是系统中所有安全区域可访问的受保护内存量的相当小的限制,这称为安全区域页面缓存或EPC。 在今天的系统上,当前仅占128 MB。 幸运的是,英特尔提供的驱动程序(是SGX SDK的一部分)可以执行对飞地内存的即时分页。 此分页转到DRAM,而不是磁盘,因此此操作会带来一些性能损失,但这并不可怕(在我们的实验中,对于以或多或少的线性方式利用内存的有效负载,这相当于少于30%的开销)。 当然,驱动程序(或主机内核)只能看到加密的和受完整性保护的页面,因此无法窃取或有意义地重新排列它们。

最后,最后一个问题(不能轻易消除)是存在各种侧信道攻击,这些攻击可能会将机密区代码中的秘密泄漏到主机OS。 考虑到攻击者可以控制整个主机OS,中和这些辅助通道尤其具有挑战性。 毫无疑问,英特尔和其他研究人员将继续研究这一领域,并可能实施越来越多的保护措施以防止此类攻击(很可能是在SDK /编译器级别?)。

尽管上面讨论了SGX的所有问题,但我仍然相信这是一项具有巨大潜力的技术,并且大多数问题都可以解决,或者至少可以在很大程度上得到改善。 但是,要使其真正有用,特别是对于用户(不仅是供应商),我们真的需要找到在SGX区域内运行整个未经修改的应用程序的通用方法。 就像它们是某种“ VM”一样。

但是,实现此目标有两个主要挑战:

  1. 首先,我们需要公开一个接近完整的API,例如POSIX或Win32(或Linux或Windows syscall API),以便在安全区中运行的进程的行为就像在本地OS上本地运行一样。 这里的挑战是,自然地,我们不能简单地直达主机,因为……主机在我们的威胁模型中不受信任。
  2. 另一个挑战是如何将安全区域内的应用程序有意义地绑定到某个秘密,该秘密稍后可用于构造证明该应用程序确实在有效的SGX安全区域内执行的证据。 在这里,我们想防止对基于飞地的计算的最明显的攻击,这种攻击是通过让攻击者……仅模拟进程在飞地中运行而实现的,但实际上是在正常执行模式下执行(例如,在Intel SGX的情况下) ,攻击者将跳过EINIT / EENTER指令)。

关于解决第一个挑战,已经提出了一些论文和项目:Microsoft Haven,SCONE,Graphene SGX和Panoply。

从安全性的角度来看,这些项目之间的主要区别在于它们如何实现类似于OS的丰富API,该API将在安全区域内向应用程序公开。

一方面,采用“最小TCB大小”方法的项目意味着这意味着他们尝试将尽可能多的API调用逻辑传递给底层主机OS,同时对从返回的结果执行一些完整性检查。主机操作系统。 Scone和Panoply已采用了这种方法,其理由是将SGX区域内的代码量最小化(即TCB的大小)应该是主要目标。

Haven和Graphene所采用的另一种方法是“最小化与主机OS的不受信任的接口”。 这里的理由是,攻击区域的大小比飞地内部的代码量更重要。

我个人同意后一种方法,因为我认为外部接口的大小和复杂性更为关键。 毕竟,如果攻击者无法访问内部代码(例如,将任意参数传递给函数),那么在该代码中可能存在错误就不会有太大问题。 通过使外部接口小而简单,我们可以在实践中以合理程度的保证来确保这一点。 因此,我们在石墨烯的基础上构建了下面讨论的解决方案。

第二个挑战通常被忽略,因为作者(尤其是学术论文)倾向于将重点更多地放在第一个问题上,通常将执行证据保留在SGX飞地中作为“未来工作”(MS Haven论文在这里是一个明显的例外)。 但是,可以说,这是任何基于飞地的解决方案中最关键的方面,否则,无论执行环境如何安全,攻击者始终可以通过使用实际有效负载的仿真攻击来破坏整个方案。将在飞地之外(或在真正的飞地内,由攻击者控制)执行。

还应考虑的一个“小细节”是飞地内部的应用程序如何生成随机数。 数十年来,操作系统和应用程序提出了各种通常令人惊讶的方法来从不同的熵源生成随机性,例如中断,鼠标,磁盘或网络使用模式等。当在某个区域中运行时,我们应牢记主机OS可以完全控制所有这些“外部”事件(只有外部事件可以带来熵,对吗?)。 这意味着主机操作系统始终可以学习应用程序将在安全区域内生成的任何密钥,从而产生任何毫无意义的远程证明方案。 幸运的是,有一个解决此问题的方法:产生随机性的硬件指令:RDRAND。 但是,如果由于某种原因该应用程序不使用RDRAND(或我们在libOS中拦截的适当的OS服务),而是尝试使用某些Do-It-Yourself方法,那么我们可能会遇到严重的问题。

几个月来,我们一直与Golem一起研究一种解决方案,以解决运行任意有效载荷(更具体地说:基于Docker Linux的容器)的问题,我想分享一下我们正确立场的一些情况。现在,以及我们想去的地方。

Golem正在构建去中心化的计算云(认为EC2与SETI @ home结合使用),基于安全区的计算为解决任何此类去中心化网络面临的两个关键问题提供了潜力:1)如何确保提供计算能力的用户确实为以下目的执行有效负载(2)为有效负载提供机密性,以便执行计算的计算机所有者无法窃听正在处理的数据。

另一方面,我们(ITL)对基于飞地的计算也非常感兴趣,其中一个自然的应用程序将用于Qubes OS的未来版本。

如上所述, 我们选择了基于Graphene SGX的解决方案 ,因为它的体系结构似乎对我们最有吸引力,如上一节所述。

不幸的是,在架构级别上看起来不错的(或者更直接地说:在纸上)在实践中却变得不那么有用了。 我们尝试在Graphene下运行的任何更复杂的有效负载(例如Blender渲染器处理任何更复杂的场景)都暴露了Graphene LibOS实现中的许多错误(主要是竞争条件)。 幸运的是,这些不是我们威胁模型中与安全性相关的错误,因为在这种情况下,我们假设攻击来自主机,而不是来自有效负载(并且恶意有效负载始终可能……对自身及其自身的数据都是恶意的,没有任何威胁可以做到这一点)。

Golem还认为攻击可能来自攻击主机的潜在恶意负载。 为了防止它们,他们使用了另一种不依赖于石墨烯的沙盒技术。 这是一个需要强调的重要细节,因为Graphene实际上确实将自己作为框架进行广告,从而对有效负载进行沙箱处理。 但是,我们对代码的快速分析表明,这种额外的功能不能很好地起作用,并且可以相对容易地绕开。

原始Graphene项目的另一个问题是无法向远程方(即用户)证明有效载荷确实已在适当的区域,受到适当的保护下执行(上面讨论的第二个挑战)。

我们花了几个月的时间来查找和修复Graphene中的错误,并且还设计和实施支持以确保远程方确实在适当保护的区域内完成数据的执行和处理。

我们针对后一个挑战的解决方案已针对类似批处理的有效载荷进行了设计,这些有效载荷将一些文件作为输入,进行计算(例如渲染场景的一部分),然后在完成后创建一些输出。 将来,它也可以扩展到覆盖更多的交互式有效载荷。 向用户提供了一个工具,该工具负责自动验证远程证明证明,并使用由我们在飞地内运行的框架生成的公钥来加密输入文件。 这样,用户就可以确保自己的数据只能通过以下方式解密:1)具有特定度量的有效负载(代码的哈希值或开发人员签名密钥的哈希值),2)在适当的SGX区域内运行,3)在适当的位置运行,例如非越野车硬件,4)具有适当的属性集(例如,不在SGX调试模式下)。

鉴于我们对Graphene进行的修改量很大,并且由于我们的开发进度要比最近的Graphene项目快得多,因此我们决定分叉该项目 。 我们将在接下来的几周内(最有可能在暑假之后)将存储库公开,并提供一份技术论文,描述我在上文中快速尝试总结的挑战。 今天我们只想在below以下展示一部短片演示电影

我们还要感谢原始的Graphene维护者和所有参与此令人兴奋项目的贡献者!


事不宜迟,让我们看一下演示🙂

在上面的演示中,展示了几个步骤(它们只能由应用程序供应商来完成,而不是由有效负载的用户来完成):

  1. 首先,我们正在构建基本的Docker容器,其中包含必要的基于石墨烯的基础架构: golem-sgx-template
  2. 然后,我们为示例性应用程序容器创建一个Dockerfile,在这种情况下,该容器用于在SGX飞地( golem-sgx-blender )内运行Blender:

如我们所见,Dockerfile继承自golem golem-sgx-template ,然后它是一个非常标准的Dockerfile,除了两件事:1)我们需要运行一个特殊的脚本来为负载创建一个所谓的清单(更多内容)。 2)使用包装器脚本( /graphene_sgx_run.sh ,也包含在基本Docker模板中)启动实际的有效负载,该脚本负责在Graphene下运行给定的可执行文件,确保已打开特定的选项(例如告诉它使用支持SGX的PAL)。

上面提到的有效负载清单是至关重要的事情:它包含所有文件的列表,这些文件应可用于SGX飞地中运行的有效负载。 这包括输入和输出文件,这些文件由相应的用户端工具自动加密并进行完整性保护,以使只有有效SGX安全区中的适当有效负载才能读取和写入它们。 对于Golem应用程序,此过程将是全自动的(如上所示),但是对于其他情况,容器供应商可能需要通过定义不同的输入和输出文件列表来调整此清单。 其他文件(例如所有库和其他依赖项的列表)将自动生成,并且在所有情况下均适用。 即将发表的论文中有更多详细信息。

3.现在,我们准备构建并签署最终的Docker映像。 现在,托管给定负载(在本例中为Blender渲染器)的Docker映像已完成(通过上面制作的数字签名进行密封),并可供用户运行。

有了这样的最终docker镜像,任何人现在都可以使用简单的包装脚本运行它(例如Golem网络的计算节点),例如:

那么,从长远来看,我们对英特尔SGX的计划和期望是什么?

首先,我们期待英特尔实现“ SGX解放”,正如我所称的。 解放应该包括两个独立的方面:

  1. 解放远程认证,这意味着英特尔应该允许任何人(不仅是其自己的IAS服务器)执行报价验证(当然,这很好,并且如果英特尔继续经营并向发现这种服务方便的客户提供IAS,则可能是有道理的),
  2. 允许加载使用任何密钥签名的飞地,而不仅仅是英特尔“祝福”的飞地。 但是同时仍然允许有意义的远程认证工作。 通过有意义的证明,我理解了使用从处理器的私钥派生的密钥对Quote进行签名的人。

我们认为对于进一步采用SGX技术至关重要的其他方面是:

  • 允许安全区和GPU之间的安全通信路径。 这对于像Golem一样的应用程序(有效负载可能要利用GPU进行计算)以及对于像客户一样的应用程序(我们希望某些用户应用程序,例如消息传递应用程序或电子邮件客户端)都非常重要。能够安全地向用户显示解密的内容,而无需担心(不受信任的)主机OS看到并捕获它。
  • 另外,允许与鼠标和键盘(或通常为HID设备)进行安全通信,以促进在客户端应用程序中的安全使用,例如刚才提到的消息传递,电子邮件,银行业务和类似钱包的应用程序。
  • 增加EPC的数量,以方便在飞地中运行大型,复杂的有效负载,而对性能的影响最小。

要了解有关Joanna与ITL合作的更多信息,请单击此处。

在推特上关注乔安娜