瞬态执行攻击与防御的评估

作者:Claudio Canella, Jo Van Bulck, Michael Schwarz, Moritz Lipp, Benjamin von Berg, Philipp Ortner, Frank Piessens, Dmitry Evtyushkin, Daniel Gruss:
标题:A Systematic Evaluation of Transient Execution Attacks and Defenses.
发布:USENIX Security Symposium
时间:2019

目录

  • 摘要
  • 引言
    • 贡献
  • 瞬态执行
    • 指令集体系结构和微体系结构
    • 无序执行
    • 推测性执行
    • 缓存隐蔽通道【Cache Covert Channels】
    • 瞬态执行攻击
    • 高级分类
  • Spectre型攻击
    • Spectre变体的系统化
    • 误训练策略的系统化
    • Spectre PHT(输入验证绕过)
      • 微结构元素
      • Reading 越界。
      • Writing 越界。
      • 被忽视的错误训练策略
    • Spectre BTB(分支目标注入)
      • 微建结构元素。
      • 劫持控制流程
      • 被忽视的错误训练策略
    • Spectre RSB(返回地址注入)
      • 微结构元素
      • 劫持返回流
      • 被忽视的错误训练策略
    • Spectre STL(推测性存储绕过)
      • 微结构元素
      • 阅读过时的值
  • Meltdown-type攻击
    • Meltdown变体的系统化
    • Meltdown-US (Supervisor-only Bypass)
    • Meltdown-P (Virtual Translation Bypass)
      • Foreshadow
      • Foreshadow-NG
    • Meltdown-GP (System Register Bypass)
    • Meltdown-NM (FPU Register Bypass)
    • Meltdown-RW (Read-only Bypass)
    • Meltdown-PK (Protection Key Bypass)
    • Meltdown-BR (Bounds Check Bypass)
    • Residual Meltdown (Negative Results)
      • 分部错误
      • 主管访问
      • 对准故障
      • 分段故障
      • 指令获取

摘要

对包括Spectre和Meltdown在内的瞬态执行攻击的研究表明,异常或分支预测错误事件可能会在CPU的微体系结构状态中留下秘密相关的痕迹。这一观察结果导致了新的Spectre和Meltdown攻击变体的激增,甚至导致了更多的特别防御(例如,微代码和软件补丁)。工业界和学术界现在都专注于为已知问题寻找有效的防御措施。然而,我们对剩余攻击面和拟议防御的完整性只有有限的了解。

在本文中,我们提出了一个系统化的瞬态执行攻击。我们的系统化揭示了6种(新的)暂时执行攻击,这些攻击到目前为止一直被忽视,也没有被调查:2种新的可利用的Meltdown效应:Intel上的MeltdownPK(保护密钥旁路),Intel和AMD上的Meltdown BND(边界检查旁路);以及4种新的Spectre错误训练策略。

我们通过在三家主要CPU供应商(英特尔、AMD、ARM)上的概念验证实现来评估分类树中的攻击。我们的系统化可以更全面地了解攻击面,并对防御进行更系统的评估。通过这一系统评估,我们发现大多数防御,包括部署的防御,无法完全缓解所有攻击变体。

引言

在过去的几十年里,CPU的性能通过缩小处理技术和增加时钟频率而不断提高,但物理限制已经阻碍了这种方法。为了仍然提高性能,供应商将重点转移到增加内核数量和优化指令管道上。现代CPU流水线被大规模并行化,允许先前流水线阶段的硬件逻辑提前甚至无序地执行后续指令的操作。直观地说,当前操作依赖于以前的尚未执行(和失效)的指令

因此,为了始终保持管道满,必须预测控制流、数据依赖关系,甚至可能预测实际数据。因此,现代CPU依赖于复杂的微体系结构优化来预测指令流,有时甚至重新排序。然而,至关重要的是,由于这些预测可能被证明是错误的,管道刷新可能是必要的,并且指令结果应该始终根据预期的有序指令流提交

即使没有预测机制,管道刷新也可能发生,因为在现代CPU上,几乎任何指令都可能引发故障(例如,页面故障或一般保护故障),需要在出现故障的指令之后回滚所有操作。有了预测机制,当需要部分管道刷新时,会出现更多情况,即每次预测失误时。流水线刷新将丢弃挂起指令的任何体系结构效果,从而确保功能的正确性。因此,指令是瞬态执行的(首先它们是,然后它们消失),即,我们称之为瞬态执行[50,56,85]。

虽然瞬态指令的体系结构效果和结果被丢弃,但微体系结构的副作用仍然存在于瞬态执行之外。这是Spectre[50]、Meltdown[56]和Foreshadow[85]的基础。

这些攻击利用瞬态执行,通过微体系结构副作用(例如缓存状态)对机密进行编码,攻击者稍后可以在体系结构级别恢复这些副作用。瞬时执行攻击领域突然出现并激增,导致人们不知道所有变体及其含义。这一点从令人困惑的命名方案中显而易见,该命名方案已经导致了对至少一种攻击的错误分类[48]。更重要的是,这种混乱导致了对防御的误解和错误假设。

许多防御只专注于阻碍特定隐蔽通道的利用,而不是解决泄漏的微观结构根本原因[45,47,50,91]。其他防御依赖于最近的CPU功能,这些功能尚未从瞬态安全角度进行评估[84]。我们还揭穿了隐含的假设,包括AMD或最新的英特尔CPU完全免疫Meltdown类型的影响,或者串行化指令减轻任何CPU上的Spectre Variant 1。

在本文中,我们提出了瞬态执行攻击的系统化,即Spectre、Meltdown、Foreshadow和相关攻击。使用我们的决策树,通过明确的命名方案对瞬态执行攻击进行准确分类(参见图1)。
瞬态执行攻击与防御的评估_第1张图片

我们的分类法具有层次性和可扩展性,可以轻松识别残余攻击表面,导致本工作中首次描述的6种先前被忽视的瞬态执行攻击(Spectre和Meltdown变体)。其中两种攻击是Meltdown BND,利用Intel和AMD上x86绑定指令的Meltdown类型效应;以及Meltdown PK,利用Intel上内存保护密钥的Meltdown-类型效应。其他4种攻击是之前被忽视的SpectrePHT和Spectre BTB攻击的错误训练策略。我们通过在英特尔、ARM和AMD的CPU上评估的易受攻击的代码模式的实际概念证明,在分类树中演示了攻击。

接下来,我们提供最先进的防御系统。基于此,我们通过实际实验和理论论证系统地评估了辩护,以表明哪些有效,哪些不够或不能。这一系统评估表明,我们仍然可以发起瞬态执行攻击,这些攻击本应通过推出补丁来缓解。最后,我们讨论了如何设计防御来减轻整个类型的瞬态执行攻击。

贡献

我们系统化了Spectre和Meltdown类型的攻击,推进了对攻击表面的理解,突出了错误分类,并揭示了新的攻击。

我们明确区分了设计有效对策所需的Meltdown/Spectre。

我们对防御进行了分类,并表明大多数防御,包括部署的防御,无法完全缓解所有攻击变体。

我们描述了新的分支错误训练策略,强调了根除Spectre类型攻击的困难。

我们负责任地向英特尔、ARM和AMD披露了这项工作。实验设置。除非另有说明,否则报告的实验结果是在最近的Intel Skylake i5-6200U、Coffee Lake i7-8700K和Whiskey Lake i7-1565U CPU上执行的。我们的AMD测试机是Ryzen 1950X和Ryzen Threadipper 1920X。在ARM上进行实验时,使用了NVIDIA Jetson TX1。

瞬态执行

指令集体系结构和微体系结构

指令集体系结构(ISA)提供了硬件和软件之间的接口。它定义了以下指令处理器支持、可用寄存器、寻址模式,并描述执行模型。不同ISA的例子有x86和ARMv8。【ISA是描述硬件和软件如何交互的

然后,微体系结构描述了ISA是如何在处理器中以流水线深度、元素互连、执行单元、缓存、分支预测的形式实现的。【微体系结构是描述ISA如何实现的

ISA和微体系结构都是有状态的。

在ISA中,这种状态包括,例如,成功计算后寄存器或主存储器中的数据。因此,开发人员可以观察到体系结构状态

微体系结构状态包括,例如,高速缓存和翻译后备缓冲区(TLB)中的条目,或者执行单元的使用情况。这些微体系结构元素对程序员来说是透明的,不能直接观察,只能间接观察

无序执行

在现代CPU上,复杂指令集的单个指令首先被解码,并被拆分为更简单的微操作(μOP),然后进行处理。这种设计决策允许超标量优化,并通过所谓的微码更新来扩展或修改特定指令的实现。

此外,为了提高性能,CPU通常会实现所谓的无序设计。这使得CPU不仅可以按照指令流提供的顺序执行μOP,还可以并行调度μOP,尽可能多地利用CPU的执行单元,从而提高整体性能。如果μOP所需的操作数可用,并且其相应的执行单元不忙,则即使指令流中较早的μOP尚未完成,CPU也会开始执行

由于只有在所有先前的μOP完成后,才能在体系结构级别看到即时结果,因此CPU通常会在所谓的重新排序缓冲区(ROB)中跟踪μOP的状态。CPU负责按顺序退役μOP,决定放弃其结果或将其提交到体系结构状态。例如,异常和外部中断请求在退役期间通过清除ROB中任何未完成的μOP结果进行处理。因此,CPU可能已经执行了所谓的瞬态指令[56],其结果从未提交到架构状态

推测性执行

软件大多不是线性的,而是包含指令之间的(条件)分支或数据依赖关系。理论上,CPU必须暂停,直到分支或依赖项得到解决后才能继续执行。由于停滞会显著降低性能,CPU会部署各种机制来预测分支或数据依赖关系的结果。因此,CPU继续沿着预测的路径执行,将结果缓冲在ROB中,直到预测的正确性随着其依赖性的解决而得到验证

在正确预测的情况下,CPU可以从重新排序缓冲区提交预先计算的结果,从而提高整体性能

然而,如果预测不正确,CPU需要通过压缩ROB中所有预先计算的瞬态指令结果来执行回滚到最后一个正确状态

缓存隐蔽通道【Cache Covert Channels】

现代CPU使用缓存来隐藏内存延迟。然而,这些潜伏期差异可以在侧通道和隐蔽通道中利用[24,51,60,67,92]。特别是,Flush+Reload允许以缓存线粒度在内核之间进行观察,从而实现攻击,例如对加密算法[26,43,92]、用户输入[24,55,72]和内核寻址信息[23]的攻击。对于Flush+Reload,攻击者使用clflush指令连续刷新共享内存地址,然后重新加载数据。如果受害者使用了缓存线,访问它将很快;否则,它将是缓慢的

隐蔽通道是侧通道攻击的一种特殊用例,攻击者同时控制发送方和接收方。这使得攻击者能够绕过体系结构级别存在的许多限制来泄露信息。

瞬态执行攻击

瞬态指令反映了程序预期代码和/或数据路径之外的未经授权的计算。对于功能的正确性,至关重要的是,它们的结果永远不会被提交到体系结构状态。然而,瞬态指令仍可能在CPU的微体系结构状态中留下痕迹,随后可能被用来部分恢复未经授权的结果[50,56,85]。这一观察结果导致了各种瞬态执行攻击,从高层来看,这些攻击总是遵循相同的抽象流,如图2所示。
瞬态执行攻击与防御的评估_第2张图片
【图2:瞬态执行攻击分5个阶段的高级概述:(1)准备微体系结构,(2)执行触发指令,(3)瞬态指令通过微体系结构隐蔽通道对未经授权的数据进行编码,(4)CPU撤销触发指令并刷新瞬态指令,(5)从微体系结构状态重建机密。】

(1)攻击者首先使微体系结构进入所需状态,例如,通过刷新和/或填充内部分支预测器或数据缓存。

(2)接下来是一个所谓的触发器指令的执行。这可以是导致后续操作最终被压缩的任何指令,例如,由于异常或预测错误的分支或数据依赖性。

(3)在触发指令完成之前,CPU继续执行瞬态指令序列。攻击者滥用瞬态指令充当微体系结构隐蔽通道的发送端,例如,通过将机密相关内存位置加载到CPU缓存中。【触发指令一直在跑,直到跑完发现之前跑的瞬态指令有问题。但是这些指令被充当“发送端”,相关的机密加载到了缓存。】

(4)最终,在触发指令失效时,CPU会发现异常/预测错误,并刷新管道以丢弃瞬态指令的任何体系结构影响。

(5)然而,在攻击的最后阶段,未经授权的瞬态计算结果在隐蔽信道的接收端被恢复,例如,通过定时存储器访问来从瞬态指令推断出与秘密相关的负载。【这里接受和发送都是抽象上的,所谓的发送只是信息的表征,接收只是推测信息的媒介】

高级分类

Spectre vs. Meltdown。瞬态执行攻击的共同点是,它们滥用瞬态指令(从未在体系结构上提交),以在微体系结构状态下对未经授权的数据进行编码。随着图2中抽象阶段的不同实例化,出现了各种各样的瞬态执行攻击变体。我们有意将我们的分类基于瞬态计算的根本原因(阶段1、2),从用于传输未经授权数据的特定隐蔽信道中抽象出来(阶段3、5)。这导致了我们分类树中的第一个重要分支(参见图1)。第一种类型的攻击被称为Spectre[50],利用控制或数据流预测失误后的瞬态执行。第二种类型的攻击被称为Meltdown[56],利用错误指令后的瞬态执行

重要的是,Spectre和Meltdown利用了根本不同的CPU特性,因此需要正交防御。

在前者依赖于专用的控制或数据流预测机制的情况下,后者仅利用来自故障指令的数据转发到流水线中前面的指令。请注意,虽然到目前为止,Meltdown类型的攻击利用无序执行,但即使是基本的有序管道也可能产生类似的效果[86]。本质上,触发指令的不同根本原因(Spectre型预测失误与Meltdown型故障)决定了随后未经授权的瞬态计算的性质,从而决定了攻击的范围。

也就是说,在Spectre的情况下,瞬态指令只能根据应用程序在体系结构上也被允许访问的数据进行计算。Spectre因此暂时不评估软件定义的安全策略(例如,边界检查/函数调用/返回抽象、内存存储)以从程序的预期代码/数据路径泄漏秘密。因此,就像在“困惑的副手”场景中一样,成功的Spectre攻击可以归结为引导受害者暂时计算受害者有权访问但攻击者没有访问的内存位置。在实践中,这意味着图2中的瞬态执行攻击流的一个或多个阶段应该通过在受害者应用程序中执行的所谓代码小工具来实现。我们在第5节中基于这些阶段提出了一种新的小工具分类法。

另一方面,对于Meltdown类型的攻击,瞬态执行允许通过计算错误指令的未经授权的结果来完全“融化”架构隔离屏障。因此,Meltdown暂时绕过硬件强制的安全策略,以泄漏应用程序在架构上始终无法访问的数据。Spectre类型的泄漏在很大程度上仍然是重要推测性性能优化的意外副作用,而Meltdown反映了CPU未能遵守瞬态指令的硬件级保护边界。也就是说,只需要在故障发生后继续执行瞬态,但不足以成功进行Meltdown攻击。正如第6节进一步探讨的那样,这对防御有着深远的影响。

总的来说,缓解Spectre需要仔细的硬件-软件协同设计,而仅仅用伪值替换故障指令的数据就足以阻止硅中的Meltdown型泄漏,例如,就像在AMD处理器中所做的那样,或者使用Whiskey Lake以后的最新Intel CPU中宣传的Rogue数据缓存负载电阻(RDCL_NO)功能[40]。

Spectre型攻击

在本节中,我们概述了Spectre类型的攻击(参见图1)。考虑到Spectre变体在各种对手模型中的多功能性,我们在图2中基于抽象瞬态执行攻击流的准备阶段提出了一种新的两级分类法。首先,我们区分了可以触发预测的不同微体系结构缓冲区(第2阶段),其次,可以用于引导预测的错误训练策略(第1阶段)。

Spectre变体的系统化

为了预测各种类型的分支和数据依赖性的结果,现代CPU在各种内部缓冲区和组件中积累了广泛的微体系结构状态[19]。表1概述了Spectre型攻击及其利用的相应微体系结构元素。
瞬态执行攻击与防御的评估_第3张图片

作为我们分类树的第一级,我们根据触发导致瞬时执行的预测失误的微观结构根本原因对Spectre攻击进行分类:

Spectre PHT[48,50]利用模式历史表(PHT)来预测条件分支的结果。

Spectre BTB[50]利用分支目标缓冲区(BTB)来预测分支目的地地址。

Spectre RSB[52,59]主要利用返回堆栈缓冲区(RSB)来预测返回地址。

Spectre STL[29]利用内存消除歧义来预测存储到加载(STL)数据依赖关系。

请注意,NetSpectre[74]、SGXSspectre[63]和SGXPectre[13]专注于在特定的利用场景中应用上述Spectre变体之一。因此,在我们的分类中,我们不认为它们是单独的变体。

误训练策略的系统化

我们现在为滥用基于历史的分支预测的Spectre变体提出了一种二级分类方案(即,除Spectre STL外的所有变体)。这些Spectre变体首先经历一个准备阶段(参见图2),在这个阶段,微结构分支预测状态被“毒害”,导致对特定受害者分支的故意误判

由于现代CPU[19,50]中的分支预测缓冲区通常基于分支指令的虚拟地址进行索引,因此错误训练可能发生在同一地址空间内,也可能发生在不同的攻击者控制的进程中。此外,如图3所示,当预测中只使用虚拟地址的子集时,可以使用一致虚拟地址处的分支指令来实现错误训练。因此,我们用4种不同的错误训练策略增强了Spectre型分支中毒攻击的领域:
瞬态执行攻击与防御的评估_第4张图片

【受害者进程(相同地址空间)或攻击者控制的进程(跨地址空间)都可能对分支进行不信任。可以使用易受攻击的分支本身(原位)或一致虚拟地址处的分支(异地)来实现误训练。】

1.在受害者进程中执行受害者分支(相同的地址空间)。

2.在受害者进程中执行一致分支(相同地址空间不合适)。

3.在不同的进程中执行影子分支(交叉地址空间)。

4.在不同的进程中执行一个全等分支(交叉寻址空间错位)。

在目前的文献[6,13,48,50]中,对于不同的Spectre变体,上述几种分支中毒策略被忽视了。我们在表2中总结了错误训练策略下的脆弱性评估结果。
瞬态执行攻击与防御的评估_第5张图片

因此,我们的系统化揭示了明显的盲点,使攻击者能够以以前未知的方式误认分支预测因子。正如进一步解释的那样,根据对手的能力(例如,进程内、沙盒、远程、飞地等),这些以前未知的错误训练策略可能会导致新的攻击和/或绕过现有的防御。

Spectre PHT(输入验证绕过)

微结构元素

Kocher等人[50]首先引入了Spectre Variant 1,这是一种攻击,会毒害模式历史表(PHT),从而错误预测条件分支的方向(采取或不采取)。根据底层微体系结构,PHT是基于分支指令的虚拟地址位加上隐藏分支历史缓冲区(BHB)的组合来访问的,该缓冲区累积同一物理核上最后N个分支的全局行为[18,19]。

Reading 越界。

条件分支通常被程序员和/或编译器用来在运行时维护内存安全不变量。例如,考虑以下用于边界检查的代码片段[50]:
代码
在体系结构级别,该程序清楚地确保索引变量x始终位于固定长度缓冲区数组1的边界内。然而,在重复提供x的有效值之后,PHT将可靠地预测该分支评估为true。当对手现在提供了一个无效的索引x时,CPU继续沿着一条预测错误的路径进行,并暂时执行越界内存访问。上面的代码片段提供了一个“泄漏小工具”的显式示例,它可以充当微体系结构的隐蔽通道:根据读取的越界值,瞬态指令将属于array2的另一个内存页加载到缓存中

Writing 越界。

Kiriansky和Waldsburger[48]表明,通过遵循相同的原理,瞬态写入也是可能的。请考虑以下代码行:
代码
在对PHT组件进行错误训练后,控制不可信索引x的攻击者可以临时写入任意越界地址。这会造成暂时的缓冲区溢出,使攻击者能够绕过类型和内存安全。最终,当从面向返回的编程[75]攻击,对手甚至可以通过覆盖返回地址或代码指针来获得瞬态域中的任意代码执行。

被忽视的错误训练策略

到目前为止,Spectre PHT攻击[48,50,63]依赖于相同的地址空间就地分支中毒策略。然而,我们的结果(参见表2)表明,我们测试的Intel、ARM和AMD CPU容易受到所有四种PHT错误训练策略的影响。在这篇文章中,我们率先成功演示了Spectre PHT风格的分支预测失误攻击,而无需事先执行受害者分支。这是一个重要的贡献,因为它可能为受限制的对手开辟以前未知的攻击途径。

例如,跨地址空间PHT中毒可能会对不直接接受用户输入的特权守护进程进行高级攻击。同样,对于Intel SGX技术,已经开发了远程证明方案[76],以强制受害者飞地只能运行一次。这有效地排除了当前最先进的SGXSspectre[63]攻击,这些攻击重复执行受害者飞地以误导PHT分支预测器。另一方面,我们新颖的错位PHT中毒策略允许我们通过在不可信飞地主机过程中重复执行一致分支,在同一物理核心的飞地之外完全执行训练阶段(参见图3)。

Spectre BTB(分支目标注入)

微建结构元素。

在Spectre变体2[50]中,攻击者毒害分支目标缓冲区(BTB),以将临时执行引导到预测错误的分支目标。对于直接分支,CPU使用分支指令的虚拟地址位的子集对BTB进行索引,以产生预测的跳转目标。对于间接分支,CPU使用不同的机制[28],当索引BTB时,可以考虑BHB中累积的全局分支历史。我们将这两种类型都称为Spectre BTB。

劫持控制流程

与Spectre PHT相反,Spectre BTB允许将瞬态控制流重定向到任意目的地。采用面向返回编程(ROP)攻击的既定技术[75],但滥用BTB中毒而不是应用程序级漏洞,在受害者地址空间中发现的选定代码“小工具”可能会被链接在一起,以构建任意的瞬态指令序列。因此,SpectrePHT的成功在很大程度上依赖于错误预测的代码路径上的意外泄漏,而Spectre BTB中ROP式的小工具滥用允许更直接地构建隐藏通道,暴露瞬态域的秘密(参见图2)。我们将在第5节中更详细地讨论小工具类型。

被忽视的错误训练策略

Spectre BTB最初在英特尔、AMD和ARM CPU上使用交叉地址空间原位错误训练策略进行了演示[50]。使用SGXPectre[13],Chen等人使用跨地址空间原位或同地址空间异地BTB中毒策略从Intel SGX飞地中提取机密。我们通过表2所示的系统评估,实验性地再现了这些错误训练策略。在AMD和ARM上,我们无法证明BTB中毒是不合时宜的。可能,这些CPU使用了一组未知的(子)虚拟地址位或一个我们无法进行反向工程的位函数。我们鼓励其他人调查是否需要不同的(子)虚拟地址位集来实现攻击

据我们所知,我们是第一个认识到Spectre BTB错误训练也可以通过使用有效输入重复执行易受攻击的间接分支来进行的人。与Spectre PHT非常相似,这种相同的地址空间原位BTB(Spectre BTB SA IP)中毒滥用受害者自己的执行来错误地识别潜在的分支目标预测器。因此,作为理解攻击表面和防御的重要贡献,受害者领域内的就地错误训练可以绕过广泛部署的缓解措施[4,40],这些缓解措施在进入受害者之前清除和/或划分BTB。然而,由于分支目的地地址现在由受害者代码确定,不受攻击者的直接控制,Spectre BTB SA IP无法提供任意瞬态控制流重定向的全部功能。然而,在C++等通常依赖间接分支来实现多态抽象的高级语言中,Spectre BTB SA IP可能会导致微妙的“推测类型混淆”漏洞。例如,当受害者最终使用另一TypeB的对象执行虚拟函数调用时,重复执行具有TypeA的对象的虚拟函数调用可能会无意中误认分支目标预测器,从而导致误判。

Spectre RSB(返回地址注入)

微结构元素

Maisuradze和Rossow[59]以及Koruyeh等人[52]介绍了一种利用返回堆栈缓冲区(RSB)的Spectre变体。RSB是一个小型的每核微体系结构缓冲区,用于存储最近N条调用指令之后的虚拟地址。当遇到ret指令时,CPU从RSB弹出最上面的元素来预测返回流。

劫持返回流

每当RSB布局偏离软件堆栈上的实际返回地址时,就会出现错误估计。例如,当在保护域交换机上恢复内核/飞地/用户堆栈指针时,这种差异自然发生。此外,相同的地址空间对手可以显式地覆盖软件堆栈上的返回地址,或者临时执行更新RSB的调用指令,而不产生架构效果[52]。这可能允许在沙盒中执行的不受信任的代码暂时将返回控制流转移到沙盒环境之外的感兴趣的代码小工具。

由于RSB的固定大小特性,深度嵌套函数调用会出现误判的特殊情况[52,59]。由于RSB只能存储最近N次调用的返回地址,因此在展开软件堆栈时会出现填充不足。在这种情况下,RSB不再能够提供准确的预测。从Skylake开始,Intel CPU使用BTB作为后备[19,52],从而允许由ret指令触发的Spectre BTB式攻击。

被忽视的错误训练策略

Spectre RSB已经用所有四种错误训练策略进行了演示,但仅在英特尔[52,59]上进行了演示。我们在表2中给出的实验结果将这些策略推广到AMD CPU。此外,根据ARM自己的分析[6],我们成功地在同一地址空间内毒害了RSB条目,但在ARM CPU上没有观察到任何跨地址空间泄漏。我们预计这可能会限制我们目前的概念验证代码,并鼓励其他人对此进行进一步调查

Spectre STL(推测性存储绕过)

微结构元素

现代CPU中的推测不仅限于控制流,还包括预测数据流中的依赖关系。一种常见类型的存储到加载(STL)依赖关系要求,在写入同一位置的所有先前存储完成之前,不得执行内存加载。然而,即使在管道中所有先前存储的地址已知之前,CPU的存储器消歧器[3,33,44]也可以预测哪些加载已经可以推测地执行

当消歧器预测负载不依赖于先前存储时,负载从L1数据高速缓存读取数据。当已知所有先前存储的地址时,验证预测。如果发现任何重叠,将重新执行加载和所有以下指令。

阅读过时的值

Horn[29]展示了内存消歧器的预测失误是如何被滥用以推测性地绕过存储指令的。与以前的攻击一样,Spectre STL的对手依靠适当的瞬态指令序列通过微体系结构隐蔽通道泄漏未初始化的过时值。此外,对过时指针值进行操作可能会推测性地破坏瞬态执行域中的类型和内存安全保证[29]。

Meltdown-type攻击

本节概述了Meltdown类型的攻击,并提出了一个分类方案,该方案导致发现了两个以前被忽视的Meltdown变体(参见图1)。重要的是,当Spectre类型的攻击利用(分支)预测失误事件来触发瞬态执行时,Meltdown类型的攻击依赖于CPU异常后的瞬态指令。从本质上讲,Meltdown利用了只有在失效指令时才会引发异常(即在体系结构上可见)的漏洞。在某些微体系结构中,此属性允许管道中的瞬态指令根据即将发生故障的指令的未经授权的结果进行计算。CPU的有序指令引退机制会小心丢弃此类计算的任何体系结构影响,但与上述Spectre类型的攻击一样,机密可能会通过微体系结构的隐蔽通道泄漏

Meltdown变体的系统化

我们在两个维度上介绍了Meltdown型攻击的分类。在第一级中,我们根据导致瞬态执行的异常对攻击进行分类。根据英特尔[31]将异常分类为故障、陷阱或中止,我们观察到,到目前为止,Meltdown类型的攻击已经利用了故障,但没有利用陷阱或中止。如果发生了可纠正的错误,CPU就会产生故障,也就是说,它们允许程序在解决后继续运行。陷阱在指令执行后立即报告,即当指令失效并在体系结构上可见时。中止报告一些不可恢复的错误,并且不允许重新启动导致中止的任务

在第二级中,对于页面错误(#PF),我们根据页面表条目保护位进行进一步分类(参见表3)。
瞬态执行攻击与防御的评估_第6张图片

我们还根据可以到达的存储位置以及是否跨越权限边界对攻击进行分类(参见表4)。通过这种系统化,我们发现了几个以前未知的Meltdown变体,它们利用不同的异常类型以及页表保护位,包括两个可利用的位。我们的系统分析进一步导致了AMD CPU上可利用的Meltdown类型延迟异常处理效果的首次演示。
瞬态执行攻击与防御的评估_第7张图片

Meltdown-US (Supervisor-only Bypass)

现代CPU通常具有“用户/主管”页面表属性,以表示虚拟内存页面属于操作系统内核。最初的Meltdown攻击[56]从CPU上的用户空间读取内核内存,这些CPU不会临时强制执行用户/主管标志。在触发阶段(参见图2),未经授权的内核地址被取消引用,这最终会导致页面错误。然而,在故障在体系结构上可见之前,攻击者会执行一个瞬态指令序列,例如,该序列会根据触发指令读取的特权数据访问缓存线。在最后阶段,在引发异常之后,在隐蔽通道的接收端重建特权数据(例如,Flush+Reload)

通过事务内存CPU功能(如Intel TSX[31]、异常处理[56])抑制异常,或将其隐藏在另一个瞬态执行中[28,56],可以提高攻击带宽。通过在内核空间上逐字节迭代并抑制或处理异常,攻击者可以转储整个内核。如果操作系统在内核中有直接的物理映射,那么这包括整个物理内存。虽然当内核数据驻留在CPU缓存中时,提取率要高得多,但Meltdown甚至被证明可以成功地从内存中提取未缓存的数据[56]

Meltdown-P (Virtual Translation Bypass)

Foreshadow

Van Bulk等人[85]提出了Foreshadow,一种针对Intel SGX技术的Meltdown类型攻击[30]。未经授权对飞地内存的访问通常不会引发#PF异常,而是用中止页面伪值悄悄替换(参见第6.2节)。在没有故障的情况下,不能针对SGX飞地安装普通Meltdown。为了克服这一限制,Foreshadow攻击者清除映射飞地机密的页表条目中的“present”位,确保为后续访问引发#PF。类似于Meltdown US,对手现在使用瞬态指令序列来泄露机密(例如,通过Flush+Reload隐蔽通道)。

英特尔[34]将L1终端故障(L1TF)列为Foreshadow背后的根本原因。在清除当前位或设置“保留”位的情况下访问页表条目时,会发生终端故障。在这种情况下,CPU立即中止地址转换。然而,由于L1数据高速缓存是与地址转换并行索引的,因此页表条目的物理地址字段(即帧号)仍然可以被传递给L1高速缓存。L1中存在并标记有该物理地址的任何数据现在都将被转发到临时执行,而与访问权限无关。

尽管Meltdown-P型泄漏仅限于L1数据缓存,但最初的Foreshadow[85]攻击表明,SGX的安全页面交换机制可能首先被滥用,将任意包围区页面预取到L1缓存中,甚至包括中断时存储的CPU寄存器。这突出表明,SGX的特权对手模型大大放大了瞬态执行攻击表面。

Foreshadow-NG

Foreshadow-NG[90]从对SGX飞地的攻击中概括了Foreshadow,以绕过操作系统或系统管理程序隔离。该概括建立在观察到的页面表条目中的物理帧数有时受到对手的直接或间接控制的基础上。例如,当将页面交换到磁盘时,内核可以自由使用除当前位之外的所有位来存储元数据(例如,交换分区上的偏移量)。但是,如果此偏移量是一个有效的物理地址,则该位置的任何缓存内存都会泄漏给无特权的Foreshadow OS攻击者.

更糟糕的是Foreshadow VMM变体,它允许控制访客物理地址的不受信任的虚拟机提取主机的整个L1数据缓存(包括属于系统管理程序或其他虚拟机的数据)。潜在的问题是,客户页面表中的终端故障提前了地址转换过程,导致客户物理地址被错误地传递到L1数据缓存,而没有首先转换为正确的主机物理地址[34]。

Meltdown-GP (System Register Bypass)

Meltdown-GP(最初命名为Variant 3a)[37]允许攻击者读取特权系统寄存器。它首先由ARM[8]发现并发布,随后英特尔[35]确定他们的CPU也容易受到攻击。未经授权访问特权系统寄存器(例如,viardmsr)会引发一般保护故障(#GP)。然而,与以前的Meltdown类型的攻击类似,该攻击利用错误指令后的瞬态执行仍然可以对未经授权的数据进行计算,并通过微体系结构隐蔽通道(例如,Flush+Reload)泄漏系统寄存器内容。

Meltdown-NM (FPU Register Bypass)

在上下文切换期间,操作系统必须保存所有寄存器,包括浮点单元(FPU)和SIMD寄存器。后一种寄存器很大,保存它们会减慢上下文切换的速度。因此,CPU允许延迟状态切换,这意味着FPU没有保存寄存器,而是简单地标记为“不可用”。FPU被标记为“不可用”后发出的第一条FPU指令会导致设备不可用(#NM)异常,允许操作系统在将FPU标记为再次可用之前保存先前执行上下文的FPU状态。

Stecklina和Prescher[78]提出了对上述惰性状态切换机制的攻击。攻击包括三个步骤。在第一步中,受害者执行将数据加载到FPU寄存器中的操作。然后,在第二步中,CPU切换到攻击者,并将FPU标记为“不可用”。攻击者现在发出一条使用FPU的指令,该指令会生成#NM故障。然而,在故障指令失效之前,CPU已经使用先前上下文中的数据临时执行了以下指令。因此,类似于以前的Meltdown类型攻击,错误指令之后的恶意瞬态指令序列可以通过微体系结构隐蔽通道(例如,Flush+Reload)对未经授权的FPU寄存器内容进行编码。

Meltdown-RW (Read-only Bypass)

在上述攻击[8,56,78,85]集中于跨特权级别窃取信息的情况下,Kiriansky和Waldsburger[48]提出了第一种Meltdown类型的攻击,该攻击绕过了当前特权级别内基于页表的访问权限。具体地说,他们表明瞬态执行不尊重“读/写”页表属性。在当前权限级别内临时覆盖只读数据的能力可以绕过基于软件的沙盒,后者依赖于只读存储器的硬件强制。

令人困惑的是,上述Meltdown RW攻击最初被命名为“Spectre变体1.2”[48],因为作者遵循了以Spectre为中心的命名方案。我们的系统化然而,揭示了上述利用的瞬态原因是#PF异常。因此,这种攻击是Meltdown类型的,但不是Spectre的变体。

Meltdown-PK (Protection Key Bypass)

Intel Skylake SP服务器CPU支持用户空间(PKU)的内存保护密钥[32]。此功能允许进程直接从用户空间更改页面的访问权限,即无需系统调用/超级调用。因此,使用PKU,用户空间应用程序可以实现可信部分的高效硬件强制隔离[27,84]。

我们提出了一种新的Meltdown PK攻击,以绕过PKU提供的读写隔离。如果攻击者在包含进程中执行代码,即使攻击者无法执行wrpkru指令(例如,列入黑名单),Meltdown PK也会起作用。此外,与跨特权级别的Meltdown攻击变体相比,没有软件解决方案。根据英特尔[36]的说法,可以使用地址空间隔离来缓解崩溃PK。最近的耐Meltdown Intel处理器列举了RDCL_NO加上PKU支持,进一步减轻了硅中的熔毁PK。通过这些缓解措施,可以限制瞬态执行攻击可能暴露的内存地址。

实验结果。我们在运行Ubuntu 18.04并支持PKU的AmazonEC2C5实例上测试了Meltdown PK。我们创建了一个内存映射,并使用PKU来删除读写访问。正如预期的那样,受保护的内存访问会产生#PF。然而,我们的概念验证通过具有Flush+Reload隐蔽通道的对抗性瞬态指令序列成功地泄漏了数据。

Meltdown-BR (Bounds Check Bypass)

为了便于高效的软件检测,x86 CPU配备了专用硬件指令,当遇到边界外数组索引时,这些指令会引发边界超出异常(#BR)。例如,IA-32 ISA定义了一个用于此目的的绑定操作码。虽然在随后的x86-64 ISA中省略了绑定指令,但现代英特尔CPU附带了内存保护扩展(MPX),用于高效的阵列边界检查。

我们的系统评估显示,#BR异常的熔毁型影响尚未得到彻底调查。具体而言,Intel的分析[40]只简要提到了基于MPX的边界检查旁路的可能性,而Dong等人最近的防御工作[16]强调了在MPX边界检查指令之后引入内存的必要性。他们将其归类为Spectre类型的攻击,这意味着需要lfence来防止分支预测器推测边界检查的结果。根据Oleksenko等人[64],bndcl和bndcuexert都没有对分支预测器施加压力,这表明没有发生预测。基于此,我们认为将其归类为Spectre类型的攻击是误导性的,因为没有涉及任何预测。Dong等人[16]的观察结果确实没有阐明#BR异常是MPX边界检查旁路的根本原因,他们根本没有考虑IA32边界保护。与Spectre PHT类似,Meltdown BR是一种边界检查旁路,但它没有错误训练预测器,而是利用了对引发的#BR异常的惰性处理。

实验结果。我们介绍了Meltdown BR攻击,它利用#BR异常后的瞬态执行来编码在体系结构上永远不可见的越界秘密。因此,Meltdown BR是Spectre PHT的一个异常驱动的替代方案。我们的概念验证演示了通过Flush+Road隐蔽通道的越界泄漏,该通道用于由IA32绑定(英特尔、AMD)或最先进的MPX保护(仅限英特尔)保护的阵列索引。对于英特尔,我们对支持MPX的Skylake i5-6200U CPU进行了攻击,对于AMD,我们评估了E2-2000和Ryzen Threadipper 1920X。这是第一个在AMD CPU上演示利用延迟异常处理的Meltdown型瞬态执行攻击的实验[4,56]。

Residual Meltdown (Negative Results)

我们系统地研究了其他尚未测试的异常的瞬态执行泄漏。在我们的实验中,我们始终没有发现陷阱或中止之外的瞬态执行痕迹,这使我们得出这样的假设,即只有在出现故障的情况下才可能出现崩溃(因为它们可能在指令执行过程中的任何时刻发生)。尽管如此,我们的实验失败的可能性仍然存在,而且它们是可能的。表5和图1总结了在英特尔、ARM和AMD上测试的故障类型的实验结果。
瞬态执行攻击与防御的评估_第8张图片

分部错误

对于除以零的实验,我们利用了带符号的除法指令(x86上的idiv和ARM上的div)。在我们测试的ARM上,没有例外,但除法只产生零。在x86上,除法会引发一个被零除的异常(#DE)。在我们测试的AMD和Intel上,CPU在异常后继续执行瞬态。在这两种情况下,结果寄存器都设置为“0”,这与测试ARM上的结果相同。因此,根据我们的实验,熔化DE是不可能的,因为没有实际值泄露。

主管访问

尽管在从内核访问用户空间内存时,监督模式访问阻止(SMAP)会引发页面错误(#PF),但在我们的实验中,它似乎没有任何Meltdown效应。因此,在我们的实验中,我们无法使用Meltdown SM泄露任何数据。

对准故障

在检测到未对齐的内存操作数时,CPU可以生成对齐检查异常(#AC)。在我们的测试中,未对齐内存访问的结果永远不会到达瞬态执行。我们怀疑这是因为#AC是早期生成的,甚至在操作数的虚拟地址转换为物理地址之前。因此,我们用熔化AC进行的实验没有显示出任何泄漏。

分段故障

我们一致发现,在我们的实验中,超出限制的段访问永远不会达到瞬态执行。我们怀疑,由于IA32分段设计过于简单,分段限制在早期得到验证,并立即引发#GP或#SS(堆栈分段故障)异常,而无需向ROB发送违规指令。因此,我们在Meltdown SS的实验中没有观察到泄漏。

指令获取

为了得到一个完整的画面,我们研究了在指令获取和解码阶段的Meltdown类型效应。在我们的测试系统中,我们没有成功地临时执行驻留在不可执行内存中的指令(即Meltdown XD),或者遵循无效操作码(#UD)异常(即Meltdown UD)。我们怀疑,在指令获取或解码过程中,CPU会立即处理异常,而不会首先在ROB中缓冲有问题的指令。此外,由于无效操作码的长度未定义,CPU甚至不知道下一条指令从哪里开始。因此,我们怀疑只有当微体系结构效应已经是由无效操作码本身而不是由随后的瞬态指令引起的效应时,无效操作码才会泄漏。

你可能感兴趣的:(TEE,人工智能,大数据)