Intel®软件保护扩展(Intel®SGX)支持在非特权进程中创建屏蔽飞地。虽然飞地在架构上受到保护免受恶意系统软件的影响,但英特尔SGX的特权攻击者模型可能会将飞地暴露给新的强大的侧通道攻击。在本文中,我们将硬件软件协同设计对策视为一类重要的单步攻击,它使用特权计时器中断一次精确地通过飞地执行一步,如支持的那样,例如,通过开源SGX-Step框架。这是一个强大的确定性攻击原语,已被用于广泛的高分辨率Intel SGX攻击,但到目前为止仍未缓解。
我们提出了AEX-Notify,这是一种灵活的硬件ISA扩展,它使飞地中断感知:飞地可以注册一个受信任的处理程序,以便在中断或异常之后运行。AEX-Notify 可以用作构建块,用于在软件中实现针对不同类型的基于中断的攻击的对策。通过我们的主要目标来阻止确定性单步,我们首先诊断底层硬件行为以确定启用它的根本原因。然后,我们应用学习到的见解,通过构建高效的软件处理程序和恒定时间反汇编器来透明地确定和原子地预取下一个飞地应用程序指令的工作集来消除这个根本原因。
我们在本文中提出的 ISA 扩展已合并到 Intel SGX 规范的修改版本中。
Intel®Software Guard Extensions (Intel®SGX)[16]是第一个商品可信执行环境(TEE)和第一个TEE在机密计算中得到了广泛的应用。Intel SGX能够构建称为飞地的用户空间内存的屏蔽区域。体系结构访问控制和硬件特性,如内存加密,保护Intel SGX飞地免受特权软件对手,以及一些物理攻击。应用范围从联邦学习和数据分析到可以保护各种工作负载的通用机密或屏蔽容器。重要的是,当前和未来几代 Intel Xeon 处理器通过将 Intel SGX 的受保护内存容量增加到 1500 倍,提高了对这些新兴用例的支持。
同时,Intel SGX引入了一种新的强对手模型,该模型激励了新的攻击性研究。例如,研究人员发现了侧通道方法,在不违反Intel SGX的体系结构安全属性的情况下从飞地推断机密数据。这些方法通常使用仅适用于特权软件的处理器特征来实现或放大各种侧通道分析技术[2,26,45,63 -66,69]。例如,Xu等人[71]首先展示了恶意操作系统如何操作Intel SGX飞地的页表,以便在飞地访问不同的4 KiB页面时触发故障,暴露飞地访问的代码和数据页面的无噪声跟踪。已经提出了各种解决方案来缓解这类受控通道攻击[18,47,56,59]。
剩下的未解决的问题是一类滥用特权硬件接口的攻击,例如高级可编程中断控制器 (APIC),以非常精细的时间分辨率收集侧通道测量——最终即使在最大的指令级粒度 [63]。一个名为SGX-Step[63]的开源工具使这种基于APIC的“单步”技术广泛应用于学术研究人员。随后,SGX-Step被用于针对Intel SGX的一系列高分辨率、中断驱动的侧通道攻击[2,3,7,10,19,26,30 - 32,43,45,49 - 51,54,57,60,62,64]。这些攻击的很大一部分严重依赖于SGX-Step的确定性单步能力,以完美的指令级粒度进行采样。例如,为了重建单个飞地指令的精确执行时间[28,49,64],或者通过观察稍微不平衡、页面内条件控制中单步指令的确切数量来克服先前受控通道攻击的粗粒度4 KiB空间分辨率。此外,一些攻击使用相关的“零步”技术来重放瞬态执行[58]或重复功耗测量[43]。
虽然在过去的几年里,侧通道攻击及其缓解受到了合理的关注,但细粒度执行控制技术的研究,特别是它们的缓解措施——追求的热情降低了。现有的缓解尝试基本上很短,因为它们没有解决根本原因,例如启发式地检测可疑中断率 [9, 46, 55]、观察性能监控计数器 [39] 或诉诸数据随机化方案 [38]。在实际设置中,中断检测启发式是不切实际的,其中良性中断风暴可以触发误报。性能监测缓解已被证明是脆弱和无效的[31,35]。此外,这些解决方案中的一些与现有的硬件不兼容[39,47,59],或者需要自定义编译器和几乎没有可用的(过时的)CPU扩展,如Intel®事务同步扩展(Intel®TSX)[9,38,55]。
在本文中,我们提出了原则性实验,阐明了允许SGX Step单步执行Intel SGX飞地的硬件行为的真正根本原因。我们的研究结果表明,仅通过硬件修改是不可能减轻SGX步骤的。因此,我们提出了一种新的软硬件协同设计方法。硬件组件是英特尔SGX的指令集体系结构(ISA)扩展,名为AEX Notify,它允许飞地在飞地中断或遇到异常时选择接受处理器发出的通知。该软件组件位于受信任的包围区屏蔽运行时中,由一个恒定时间反汇编程序和一个特制的汇编存根组成,该存根通过原子预取其工作集来透明地加快包围区应用程序执行的下一条指令,从而使应用程序指令在统计上不太可能被计时器中断“击中”。
我们使用经验证据和统计推理来评估缓解措施在多大程度上阻止对手决定性地单步执行飞地指令流。此外,我们对现有中断驱动的Intel SGX攻击进行了全面分类,并得出结论,我们提出的防御可能会挫败严重依赖确定性单步执行的攻击,包括强大的中断延迟[28,49,64]和中断计数[2,3,36,45,62]基元,同时更一般地限制Intel SGX侧通道[10,20,26,27,30,32,41,44,57]或采用频繁中断驱动探测的瞬态执行[51,54,60,61]攻击的时间分辨率。
本文中提出的ISA扩展已纳入英特尔SGX规范的最新修订版[12]。最后,我们简要介绍了使用AEX-Notify可以减轻的其他攻击。
我们提出了一种新的软硬件协同设计,称为AEX Notify,允许Intel SGX飞地软件通过在软件中部署缓解措施来缓解中断驱动的攻击。我们通过将这种方法应用于完全破坏针对英特尔SGX飞地的确定性单步攻击,证明了这种方法的可行性。
我们设计并实现了一种新颖的恒定时间指令解码器,该解码器允许缓解措施,以保护绝大多数x86指令免受恶意单步执行或零步执行的影响(例如,106个英特尔SGX运行时二进制文件中98.0%的指令)。
我们确定了启用SGX Step使用的恶意单步执行技术的硬件行为。这一分析为前两项贡献提供了信息。
我们通过在攻击者喜欢的实验设置中的经验观察,结合统计推理,来评估我们方法的有效性。
我们提出的ISA扩展已被英特尔采用。
内存管理。Intel SGX飞地是进程中受硬件保护的虚拟内存连续区域。包围区外的线程不能执行包围区内的代码,也不能从包围区读取数据。飞地的页面表位于飞地之外,由不受信任的操作系统管理。因此,Intel SGX使用受保护的包围区页面缓存映射来保持包围区内存转换的完整性。然而,这种机制并不能阻止操作系统操纵其他分页控制,例如当前(P)、已访问(A)和脏(D)位,这些位已被用于演示针对Intel SGX的新型侧信道攻击[65,66,71]。英特尔SGX还在进入和退出飞地时刷新飞地地址的转换后备缓冲区(TLB)条目[16]。这样可以防止过时的虚拟地址转换可能违反“英特尔SGX”的机密性和完整性属性。
执行控制。包围区可以具有一个或多个线程控制结构(TCS),每个线程控制结构定义包围区内的固定入口点。线程通过调用带有飞地的一个TCS地址的EENTER指令来进入飞地。线程通过调用EEXIT指令退出包围区。Intel SGX SDK将EENTERand EEXIT组成一个称为ecall[33]的抽象,类似于调用从共享对象或DLL导出的函数。相反,SDK还将EEXIT和EENTERinto组合为一个ocall抽象,允许飞地向外调用不受信任的函数。因为TCS允许一个固定的入口点,所以SDK的飞地入口逻辑必须检查寄存器参数和/或内部状态,以确定是执行ecall、ocall还是处理异常。
Intel SGX飞地也可能遇到异步退出事件,包括处理器间中断(IPI)、计时器来自APIC的中断以及诸如页面故障之类的异常。这些事件中的任何一个都会触发异步包围区退出(AEX),它将当前处理器上下文保存到包围区内的状态保存区域(SSA)帧中,该帧由称为TCS.CSSA(当前SSA)的TCS字段索引。保存上下文后,AEX会增加TCS.CSSA。不受信任的软件稍后可以调用ERESUME指令,该指令会减少TCS.CSSA并从SSA[TCS.CSA]恢复处理器上下文,从而允许线程在触发AEX时恢复飞地执行。如果飞地必须处理异常(例如,由执行不受支持的指令触发),则不受信任的运行时可能会调用EENTER。处理程序可以确定并解决异常的原因,例如,通过检查和修改SSA[0]的内容。线程然后可以EEXIT该处理程序并ERESUME该包围区应用程序。与ERESUME不同,EENTER不递减TCS.CSSA。因此,第二个AEX将把处理器上下文保存到SSA[1],在第一个AEX期间保持保存到SSA[0]的上下文不变。
这些指令和SSA框架之间的交互如图1所示。请注意,大多数英特尔SGX运行时都使用两阶段异常处理程序设计。第一阶段在SSA[1]上下文中执行,并经过仔细实现,以避免触发需要第三个SSA帧处理的异常。如果第一阶段无法诊断或解决异常,它将扩展调用堆栈,将SSA[0]的内容复制到堆栈,并重定向SSA[0]的指令指针以指向第二阶段异常处理程序。线程通过EEXITing第一个然后调用ERESUME“跳转”到第二个阶段。第二阶段可以查询由包围区应用程序注册的自定义异常处理程序。这种设计的好处是,可以处理的嵌套异常的数量受到调用堆栈大小的限制,而不是SSA帧的数量。因此,大多数飞地每个线程只分配两个SSA帧。
存在许多微结构侧通道攻击,它们要么早于TEE,要么独立于TEE而存在。例如,在Intel SGX公开的八年前就已经描述了缓存集争用攻击,如PRIME+PROBE[48],最近Aldaya等人[4]描述了跨任何类型执行环境的同时多线程(SMT)端口争用攻击(例如,用户对用户、用户对内核、用户对TEE等)。
值得强调的是,这些侧通道攻击并不违反Intel SGX的体系结构安全属性。Intel 的 SGX 开发人员参考明确指出:“Intel®Software Guard Extensions 并非旨在处理侧通道攻击或逆向工程。多达Intel®SGX开发人员构建不受这些类型的攻击保护的飞地”[33]。这种类型的保护可以通过严格遵守恒定时间编程原则来实现,这在规模上具有挑战性,并且在加密社区之外没有看到广泛采用。因此,机密计算工作负载可能容易受到恶意单步放大的侧通道攻击。
SGX-Step[63]是一个开源框架,它允许特权软件对手通过使用APIC定时器中断通过生产Intel SGX飞地精确单步执行。尽管调试飞地可以使用x86陷阱标志简单地单步执行,但生产飞地从未打算由不受信任的代码单步执行。
SGX-Step 提供了两个互补的接口来控制受害飞地的执行:计时器中断驱动和页面故障驱动。前者可用于一次精确地推进飞地一条指令,而后者可用于受控通道攻击[71],以粗粒度4 KiB粒度(我们在这项工作中考虑了范围外)破坏所选代码或数据页面访问。或者,页面错误接口也可以被滥用,导致对手选择的飞地指令在不前进的情况下反复故障,这种技术被称为“零步”[54,58,60]。
与之前通过自定义内核补丁进行粗粒度飞地中断[27,41,44]相比,SGX-Step大大减少了武装计时器和受害飞地执行之间的代码数量。因此,计时器间隔预测通过直接从用户空间配置内存映射APIC定时器寄存器来大大简化,在用ERESUME重新进入飞地之前。默认情况下,SGX-Step以一次性模式操作APIC定时器,要求开发人员指定合适的定时器间隔,以便在ERESUME之后可靠地着陆第一个Enclave指令中的中断。这种特定于平台的配置参数可以通过使用攻击者控制的调试飞地的校准工具来确定。
一些研究报告了SGX-Step的高精度单步结果(cf.第 3 节)。在具有数十万条指令的基准飞地的原始评估[63]中,发现绝大多数SGX-Step中断(>97%)在ERESUME之后到达第一个飞地指令,即强制飞地“单步”并做出恰好一条指令进度。至关重要的是,没有观察到“多步”事件,发现所有剩余的中断都落在 ERESUME 本身内,即导致 enclave “零步”并且没有架构进度。此外,最近的SGX-Step扩展[45,64]观察到,通过检查Enclave的代码页表条目(PTE)中的“访问”位,可以很容易地检测和确定性地过滤掉这样的零步骤事件,当中断到达ERESUME后并且至少有一个Enclave指令确实被退役时,处理器将只设置。因此,在配置排除了多步的保守计时器间隔后,SGX-Step 以完美的指令级粒度实现了无噪声的单步。
本节概述了已发表的攻击,这些攻击严重依赖于SGX-Step一次强制“单步”生产飞地的能力,从而激发了本文中描述的缓解。
在单步执行期间,中断会被延迟到指令失效,因此,为中断提供服务的响应时间取决于在受害者包围区中执行的指令。因此,中断本身代表了微体系结构泄漏的一个微妙来源,使单步执行的对手能够有效地将从开始到结束的飞地执行时间划分为一个更具说服力的单个指令时序序列。
这一见解首次在Nemesis[64]攻击中得到证明,该攻击使用SGX步骤收集中断延迟跟踪,描述每个单独飞地指令的执行时间。Nemesis表明,这种中断延迟跟踪可能会揭示被中断包围区指令的几个细粒度微体系结构属性,包括操作码、操作数值、页表遍历和缓存未命中。此外,中断延迟已被用于推断存储缓冲区占用情况(存储缓冲区在AEX上刷新)[28]。最近,Frontal[49]攻击扩展了Nemesis,并利用SGXStep研究了基于包围存储指令对齐的细微中断延迟变化。
Frontal和Nemesis都严格依赖于确定性的单步执行来精确采样单个飞地指令,并将不同执行的测量值关联起来。换句话说,如果没有SGX Step保证一次只执行一条指令,它们的准确性和范围将受到严重阻碍。
中断计数。至关重要的是,与臭名昭著的嘈杂定时通道形成鲜明对比的是,完全中断并因此计算在受害飞地中执行的指令数量的能力允许确定性地利用与受害飞地的单次运行(例如,紧密循环或一次性密钥生成)最微小的控制流偏差。
Van Bulk等人[62]构建了一个无噪声的空字节预言器,该预言器使用SGX Step来精确计数strlen()迭代在英特尔SGX SDK的稍微不恒定的时间字符串指针验证逻辑中,实现了完整的AESNI密钥恢复。CopyCat[45]明确地将中断计数识别为一种有能力的攻击原语,它添加了确定性的时间维度,以克服先前受控信道攻击[71]的相对粗粒度的4 KiB页面级空间粒度。CopyCat使用SGXStep从几个流行的加密库中确定地提取完整的密钥,并击败了明确旨在抵御SGX Step的最先进的编译器强化技术[29]。Aldaya等人[2,3]同样利用SGX Step的指令粒度页面访问跟踪来从经过审查的加密库中恢复完整密钥。Kim等人[36]同样通过计算页面访问之间的指令数量来识别飞地软件版本。
与上面的中断延迟测量一样,确定性单步执行的完美精度对于这些中断计数攻击的实用性至关重要;它们重构了极其微妙的页内和缓存行内控制流,这些控制流最终可能只在一条指令中发生偏差,否则将无法确定地检测到。此外,在实际攻击中,在受害者飞地的一次运行中,几个这样复杂的分支往往必须在紧密的循环中连续完美地重建。
像SGX Step这样的单步框架的最通用应用是通过以最大时间分辨率收集任意侧信道样本来放大已知的侧信道攻击,即,最终在每个单独的包围区指令之后。
这种中断驱动的攻击已被重复应用于CPU高速缓存侧通道[10,20,27,30,44,57],允许在紧密循环中准确地探测与秘密相关的数据访问,或挫败软件预取缓解措施。同样,精确的SGX Step中断功能已被用于通过分支预测器[32,41]揭示高分辨率、页内秘密相关的控制流,或探测指令粒度x86分段[26]、对齐[62]或浮点[6]异常。最后,在瞬态执行[51,54,60,61]或接口[7,19]攻击的背景下,SGX步骤也被用来精确地推进包围区,直到到达所选择的感兴趣的小工具。
除了一次推进一条指令的包围区执行外,定时器中断或页面故障也可能被滥用,在不进行架构向前推进的情况下强行暂停或“零步”受害者包围区。
零步进最初是作为一种无限制的预取机制引入的,用于将敏感CPU寄存器从SSA内存重新加载到微体系结构缓冲区中,这些缓冲区随后可能通过瞬态执行泄漏[54,60]。MicroScope[58]认识到,虽然零步进不会在架构上推进指令指针,但受害者包围区仍可能在发生故障的触发指令之后短暂执行少量操作。这些瞬态指令从未在体系结构上被提交,因此可以是无限的通过零步进重放,本质上允许在受害者飞地的单个体系结构运行期间收集任意多个(有噪声的)微体系结构资源利用率样本。这种零步进已被滥用,极大地放大了AES中秘密相关数据访问的侧信道泄漏或算术运算的端口争用[58],以及功耗测量[43]。
中断本身通过中断延迟、中断计数或瞬态重放泄漏细粒度的侧通道信息。利用这种类型的泄漏在很大程度上取决于受害者飞地没有中断意识,并且一次只能强制执行零个或一个指令。此外,中断还可以作为一种有能力的攻击原语,以最大限度地提高现有侧信道的时间分辨率。这使得对手能够可靠地瞄准在实践中可能不可行利用的代码模式,或者击败依赖指令流的部分原子行为的防御[23,41,44]。
确定性单步执行是此类中断驱动攻击的基本构建块,这些攻击已被反复证明在软件中既有效又难以缓解。