Spectre Attacks: Exploiting Speculative Execution 翻译

abstract

现代处理器使用分支预测和推测执行来最大化性能。例如,如果分支的目标依赖于正在读取的内存值,cpu将尝试猜测目标并尝试提前执行。当内存值最终到达时,CPU要么丢弃要么提交推测性计算。推测逻辑在执行方式上是不可靠的,它可以访问受害者的内存和寄存器,并且可以执行具有可测量的副作用的操作。
Spectre攻击包括诱导受害者进行推测性的操作,而这些操作在正确的程序执行过程中是不会发生的,并且会通过一个旁路将受害者的机密信息泄露给敌方。本文描述了结合了侧通道攻击、故障攻击和可从受害者进程中读取任意内存的面向返回编程的方法的实际攻击。更广泛地说,本文表明,推测性执行实现违反了支撑众多软件安全机制的安全假设,包括操作系统进程分离、容器化、即时(JIT)编译以及缓存定时和侧通道攻击的对策。这些攻击是对实际系统的严重威胁,因为在数十亿设备中使用的Intel、AMD和ARM的微处理器中发现了易受攻击的推测性执行能力。
虽然临时处理器的对策可能在某些情况下,解决方案将需要修复处理器设计以及更新指令集架构(isa)给硬件架构师和软件开发人员一个共同的理解计算状态CPU实现什么和不允许泄漏。

I. INTRODUCTION

由物理设备执行的计算通常会留下明显的副作用,超出计算的名义输出。旁道攻击的重点是利用这些副作用来获取无法获取的秘密信息。自90年代末[43]出现以来,许多物理效应,如功耗[41、42]、电磁辐射[58]或声学噪声[20],都被用来提取密码学密钥和其他秘密。
物理侧信道攻击也可以用于从复杂的设备如pc和移动电话中提取秘密信息[21,22]。然而,由于这些设备经常执行来自潜在未知来源的代码,它们面临着基于软件的攻击形式的额外威胁,这种攻击不需要外部测量设备。虽然有些攻击利用软件漏洞(如buffer overflows [5] 或 double-free errors [12]),但其他软件攻击利用硬件漏洞来泄漏敏感信息。后一种类型的攻击包括利用缓存定时[8,30,48,52,55,69,74]、分支预测历史[1,2]、分支目标缓冲区[14,44]或打开DRAM行[56]的微架构攻击。基于软件的技术也被用来安装改变物理内存[39]或内部CPU值的错误攻击[65]。
在过去的几十年里,一些微架构设计技术促进了处理器速度的提高。其中一个改进是推测性执行,它被广泛用于提高性能,包括让CPU猜测可能的未来执行方向,并在这些路径上过早地执行指令。更具体地说,考虑这样一个例子:程序的控制流依赖于位于外部物理内存中的未完成的值。由于此内存比CPU慢得多,所以通常需要几百个时钟周期才能知道该值。与通过空闲浪费这些周期不同,CPU尝试猜测控制流的方向,保存其寄存器状态的检查点,并在猜测的路径上推测地执行程序。当值最终从内存到达时,CPU检查其初始猜测的正确性。如果猜错了,CPU通过将寄存器状态恢复到存储的检查点来丢弃不正确的推测性执行,从而导致与空闲相当的性能。但是,如果猜测是正确的,那么将提交推测性执行结果,由于在延迟期间完成了有用的工作,从而获得显著的性能收益。
从安全的角度来看,投机性执行涉及到以可能不正确的方式执行程序。然而,由于cpu的设计是通过将不正确的推测性执行的结果恢复到它们之前的状态来维护功能正确性,所以这些错误在以前被认为是安全的。

A.Our Results

在本文中,我们分析了这种不正确的推测执行的安全含义。我们提出了一类微架构攻击,我们称之为Spectre攻击。在较高的层次上,Spectre攻击诱使处理器推测性地执行在正确的程序执行下不应该执行的指令序列。当这些指令对名义CPU状态的影响最终被恢复时,我们称它们为暂态指令(transient instructions)。通过影响推测性地执行哪些暂态指令,我们能够从受害者的内存地址空间中泄漏信息。
我们通过利用暂态指令序列在非特权的本地代码和可移植的JavaScript代码中跨安全域泄漏信息,从经验上证明了Spectre攻击的可行性。
使用本机代码进行攻击 作为概念验证(POC),我们创建了一个简单的受害程序,该程序在其内存地址空间中包含秘密数据。接下来,我们搜索已编译的受害二进制文件和操作系统的共享库,以查找可用于从受害地址空间泄漏信息的指令序列。最后,我们编写了一个攻击程序,该程序利用CPU的推测性执行特点,将以前找到的序列作为暂态指令。使用这种技术,我们能够从受害者的地址空间读取内存,包括存储在其中的秘密。
使用JavaScript和eBPF进行攻击 除了使用本机代码破坏进程隔离边界之外,Spectre攻击还可以用来破坏沙箱,例如,通过可移植的JavaScript代码挂装沙箱。通过经验验证,我们展示了一个JavaScript程序,它成功地从运行它的浏览器进程的地址空间读取数据。此外,我们还演示了如何在Linux中利用eBPF解释器和JIT进行攻击。

B Our Techniques

在较高的级别上,Spectre攻击通过将推测性执行与通过微架构隐蔽通道进行的数据过滤相结合,从而违反了内存隔离边界。更具体地说,要发起Spectre攻击,攻击者首先要在进程地址空间中定位或引入一系列指令,这些指令在执行时充当隐蔽的通道发射器,泄漏受害者的内存或寄存器内容。然后攻击者推测性地欺骗CPU并错误地执行这个指令序列,从而通过隐蔽通道泄漏受害者的信息。最后,攻击者通过隐蔽通道获取受害者的信息。虽然这种错误的推测性执行所导致的对名义CPU状态的更改最终会被恢复,但是之前泄漏的信息或对其他CPU微体系结构状态(例如缓存内容)的更改可以在名义状态恢复后继续存在。
上面关于Spectre攻击的描述是一般的,需要具体实例化,用一种方法来诱导错误的推测性执行,以及用一个微架构的隐蔽通道。虽然对于隐蔽通道组件有多种选择,但本工作中描述的实现使用基于cache的隐蔽通道[64],即, Flush+Reload [74], Evict+Reload[25,45]。
我们现在开始描述我们的技术,即诱导和影响错误的投机执行。
变种 1: Exploiting Conditional Branches 在Spectre攻击的这种变体中,攻击者诱使CPU的分支预测器错误地预测了分支的方向,导致CPU通过执行本来不会执行的代码,暂时违反了程序语义。正如我们所展示的,这种不正确的推测性执行允许攻击者读取存储在程序地址空间中的秘密信息。实际上,考虑以下代码示例:
在这里插入图片描述
在上面的例子中,假设变量x包含攻击者控制的数据。为了确保对array1的内存访问的有效性,上面的代码包含一个if语句,其目的是验证x的值是否在一个合法的范围内。我们展示了攻击者如何绕过这个if语句,从而从进程的地址空间读取潜在的秘密数据。首先,在初始误译阶段,攻击者使用有效的输入调用上面的代码,从而训练分支预测器期望if为真。接下来,在攻击阶段,攻击者使用array1界限之外的x值调用代码。结果,而不是等待确定分支CPU猜测界限检查将是真实的,已经大胆执行指令,评估array2 [array1 [x] * 4096]使用恶意x。注意,从array2中读取的数据使用恶意的x将数据加载到依赖于array1[x]的地址的缓存中,并进行缩放,以便访问不同的缓存线路并避免硬件预取的影响。
当边界检查的结果最终被确定时,CPU发现它的错误,并恢复对其名义微体系结构状态所做的任何更改。但是,**对缓存状态所做的更改不会被恢复,因此攻击者可以分析缓存内容,并在从受害者的内存中读取的越界读取中找到潜在的秘密字节的值。
变种2:利用间接分支。根据面向返回的编程(ROP)[63],在这种变体中,攻击者从受害者的地址空间中选择一个gadget,并影响受害者推测性地执行这个gadget。与ROP不同,攻击者不依赖于受害者代码中的漏洞。相反,攻击者训练分支目标缓冲区(BTB)将分支从间接分支指令错误地预测到gadget的地址,从而导致gadget的投机性执行。与前面一样,虽然不正确的推测执行对CPU名义状态的影响最终会恢复,但它们对缓存的影响不会恢复,因此允许小部件通过缓存端通道泄漏敏感信息。我们通过经验证明了这一点,并展示了gadget选择是如何允许这种方法读取受害者的任意内存的。
为了误导BTB,攻击者在受害者的地址空间中找到gadget的虚拟地址,然后对该地址执行间接分支。这种训练是在攻击者的地址空间中完成的。不管攻击者的地址空间中的gadget地址是什么;所需要的只是攻击者在训练期间的虚拟地址与受害者的虚拟地址匹配(或别名)。事实上,只要攻击者处理异常,即使攻击者的地址空间中没有映射到小工具的虚拟地址的代码,攻击也可以工作。(不太明白)。
其他变体。可以通过改变实现推测性执行的方法和泄漏信息的方法来设计进一步的攻击。示例包括mistraining return instructions、通过时间变化泄漏信息和算术单元争用。

C. Targeted Hardware and Current Status

Hardware。我们已经通过经验验证了几个Intel处理器在Spectre攻击下的脆弱性,包括Ivy Bridge, Haswell, Broadwell, Skylake,和Kaby Lake处理器。我们还验证了该攻击对AMD Ryzen cpu的适用性。最后,我们还成功地组织了Spectre对流行手机上的几款基于arm的三星和高通处理器的攻击。
Current Status。使用负责任的披露实践,这篇论文的独立作者小组向部分重叠的CPU供应商和其他受影响的公司提供了我们的结果的初步版本。在与工业界的协调下,作者还参与了对结果的封锁。Spectre族的攻击记录在CVE-2017-5753和CVE-2017-5715中。

D. Meltdown

Meltdown[47]是一个相关的微体系结构攻击,它利用无序执行来泄漏内核内存。Meltdown和Spectre攻击有两个主要的区别。首先,与Spectre不同,Meltdown不使用分支预测。相反,它依赖于这样一种观察:当一条指令导致一个陷阱时,在终止之前乱序执行接下来的指令。其次,Meltdown利用了许多Intel和一些ARM处理器特有的漏洞,允许某些推测性执行的指令绕过内存保护。结合这些问题,Meltdown从用户空间访问内核内存。这种访问会导致一个陷阱,但是在陷阱发出之前,访问之后的指令会通过一个缓存隐蔽通道泄漏所访问的内存的内容。
相比之下,Spectre攻击的范围更广,包括大多数AMD和ARM处理器。此外,KAISER机制[29]已经被广泛应用来缓解熔解攻击,但它并不能保护Spectre。

II. BACKGROUND

在本节中,我们将介绍现代高速处理器的一些微体系结构组件,它们如何提高性能,以及它们如何泄漏运行程序中的信息。我们还描述了面向返回的编程(ROP)和gadget。

A.Out-of-order Execution

无序执行范例增加了处理器组件的利用率,因为它允许沿着程序的指令流向下的指令与指令并行执行,有时甚至在指令之前执行。
现代处理器在内部使用微操作系统,模拟体系结构的指令集,即,指令被解码成微操作[15]。一旦与一条指令相对应的所有微操作以及之前的所有指令都完成了,这些指令就可以退役,将它们的更改提交到寄存器和其他体系结构状态,并释放重新排序缓冲区空间。因此,指令按照程序执行顺序退役。

B. Speculative Execution

处理器通常不知道程序的未来指令流。例如,当out-of-order执行到达一个条件分支指令时发生这种情况,该条件分支指令的方向依赖于尚未完成执行的前一个指令。在这种情况下,处理器可以保持当前的寄存器状态,对程序将遵循的路径做出预测,并推测地沿着该路径执行指令。如果预测结果是正确的,那么就会提交推测执行的结果(即(保存),从而获得与等待期间空闲相比的性能优势。否则,当处理器确定它走了错误的路径时,它会放弃推测性地执行的工作,通过恢复它的寄存器状态并沿着正确的路径恢复。
我们指的是执行错误的指令(错误预测的结果),但可能会留下微结构上的痕迹,如瞬态指令。虽然推测性的执行维护程序的体系结构状态,就好像执行遵循正确的路径一样,但是微体系结构元素可能处于与瞬时执行之前不同的(但有效的)状态。现代cpu上的推测执行可以运行数百条指令。该限制通常由CPU中重新排序缓冲区的大小决定。例如,在Haswell微体系结构上,重新排序缓冲区有足够的空间容纳192个微操作[15]。由于微操作的数量和指令之间没有一一对应的关系,所以限制取决于所使用的指令。

C. Branch Prediction

在猜测执行期间,处理器对分支指令的可能结果进行猜测。更好的预测通过增加可以成功提交的推测性执行操作的数量来提高性能。
现代Intel处理器的分支预测器,例如Haswell Xeon处理器,对于直接分支和间接分支有多种预测机制。间接分支指令可以跳转到运行时计算的任意目标地址。例如,x86指令可以跳转到寄存器、内存位置或堆栈上的地址,例如“jmp eax”、“jmp [eax]”和“ret”。间接分支也支持ARM(例如,“MOV pc, r14”)、MIPS(例如,“jr $ra”)、RISC-V(例如,“jalr x0,x1,0”)和其他处理器。为了补偿与直接分支相比的额外灵活性,使用至少两种不同的预测机制[35]对间接跳转和调用进行了优化。
英特尔[35]中的处理器预测
•“直接调用和跳跃(Direct Calls and Jumps)”以静态或单调的方式
•“间接调用和跳跃(Indirect Calls and Jumps)”以单调的方式,或以不同的方式,这取决于最近的程序行为,
•“条件分支(Conditional Branches)”分支目标和是否采取分支。
因此,使用几个处理器组件来预测分支的结果。分支目标缓冲区(BTB)保持从最近执行的分支指令的地址到目标地址[44]的映射。处理器可以使用BTB来预测未来的代码地址,甚至在对分支指令进行解码之前也是如此。Evtyushkin等人的[14]分析了Intel Haswell处理器的BTB,并得出结论,只有分支地址的31个最低有效位被用来索引BTB。
对于条件分支,记录目标地址对于预测分支的结果是不必要的,因为当条件在运行时确定时,目标地址通常编码在指令中。为了改进预测,处理器维护分支结果的记录,包括最近的直接和间接分支。Bhattacharya等人[9]分析了近年来Intel处理器中分支历史预测的结构。
虽然返回指令是间接分支的一种类型,但是在现代cpu中经常使用一种独立的机制来预测目标地址。返回堆栈缓冲区(RSB)维护调用堆栈[15]中最近使用的部分的副本。如果RSB中没有可用的数据,则不同的处理器将停止执行或使用BTB作为备份[15]。分支预测逻辑,例如BTB和RSB,通常不会在物理核心[19]之间共享。因此,处理器只能从在同一核心上执行的以前的分支中学习。

D. The Memory Hierarchy

为了弥补速度更快的处理器和速度较慢的内存之间的速度差距,处理器使用连续的更小但更快的缓存层次结构。cache将内存分成大小固定的块,称为行,典型的行大小为64或128字节。当处理器需要来自内存的数据时,它首先检查位于层次结构顶部的L1 cache是否包含副本。在cache命中的情况下,即,数据在cache中找到,数据从L1 cache中检索并使用。否则,在cache丢失的情况下,将重复此过程,以尝试从下一个cache级别(最后是外部内存)检索数据。一旦读操作完成,数据通常会存储在cache中(以前cache的值会被清除以腾出空间),以备在不久的将来再次需要它。现代英特尔处理器通常有三个cache级别,每个核心有专用的L1和L2 cache,所有核心共享一个公共的L3 cache,也称为最后一级cache(LLC)。
处理器必须使用缓存一致性协议(通常基于MESI协议[35])确保每核L1和L2缓存是一致的。特别是使用MESI协议或它的一些变异意味着内存写操作在一个核心将导致相同的副本数据的L1和L2缓存其他核标记为无效的,也就是说,未来的访问这些数据在其他核将无法快速加载数据从L1和L2缓存[68]。当这种情况在特定的内存位置重复发生时,这被非正式地称为cache-line bouncing.因为内存是按行粒度缓存的,所以即使两个内核访问了映射到同一高速缓存行的不同内存位置,也会发生这种情况。这种行为称为错误共享,众所周知,它是性能问题[33]的根源。有时可以滥用缓存一致性协议的这些属性来替代使用clflush指令或[27]清除模式的缓存清除。这一行为之前被认为是促进Rowhammer攻击[16]的潜在机制。(memory cache 映射问题)

E. Microarchitectural Side-Channel Attacks

我们上面讨论的所有微体系结构组件都通过预测未来的程序行为来提高处理器性能。为了达到这个目的,它们保持依赖于过去程序行为的状态,并假设将来的行为与过去的行为相似或相关。当多个程序在同一硬件上执行时,无论是并发执行还是分时执行,由一个程序的行为引起的微体系结构状态的变化可能会影响到其他程序。这进而可能导致从一个程序到另一个[19]的意外信息泄漏。最初的微体系结构侧通道攻击利用[43]的时间变异性和L1数据缓存的泄漏来从密码原语中提取密钥[52,55,69]。多年来,通道已经在多个微体系结构组件上进行了演示,包括指令缓存[3]、lower level caches[30、38、48、74]、BTB[14、44]和分支历史[1,2]。攻击的目标已经扩展到包括协同定位检测[59]、破坏ASLR[14,26,72]、按键监测[25]、网站指纹识别[51]和基因组处理[10]。最近的结果包括跨内核和跨cpu攻击[37,75]、基于云的攻击[32,76]、对可信执行环境的攻击[10,44,61]、来自移动代码的攻击[23,46,51]和新的攻击技术[11,28,44]。
在这项工作中,我们使用Flush+Reload技术[30,74],及其变体Evict+Reload[25],用于泄漏敏感信息。使用这些技术,攻击者首先从与受害者共享的缓存中清除缓存线。在受害者执行一段时间后,攻击者度量在与被驱逐的高速缓存线对应的地址上执行内存读取所需的时间。如果受害者访问了被监控的高速缓存线路,数据将在高速缓存中,访问将是快速的。否则,如果受害者没有访问该行,读取将会很慢。因此,通过测量访问时间,攻击者可以知道受害者是否在清除和探测步骤之间访问了被监视的高速缓存线路。
这两种技术之间的主要区别是用于从缓存中清除受监视的高速缓存线路的机制。在Flush+Reload技术中,攻击者使用专用的机器指令,例如x86的clflush,来删除行。使用Evict+Reload,通过强制对存储该行的缓存集进行争用来实现驱逐,例如,通过访问加载到缓存中的其他内存位置,并且(由于缓存的大小有限)导致处理器丢弃(驱逐)随后探测的行。(- —— -)

F . Return-Oriented Programming

ROP (Return-Oriented Programming, ROP)[63]是一种技术,它允许攻击者劫持控制流,通过将在脆弱的受害者代码中找到的机器代码片段(称为gadget)链接在一起,使受害者执行复杂的操作。更具体地说,攻击者首先在受害二进制文件中找到可用的gadget。每个gadget在执行返回指令之前执行一些计算。攻击者可以修改堆栈指针,例如,指向写入外部可写缓冲区的返回地址,或者覆盖堆栈内容,例如,使用缓冲区溢出,可以使堆栈指针指向一系列恶意选择的gadget地址的开头。执行时,每个返回指令从堆栈跳转到目标地址。因为攻击者控制着这一系列的地址,所以每次返回都会有效地跳转到链中的下一个gadget。(这个具体做法

III. ATTACK OVERVIEW

Spectre攻击会诱导受害者进行推测性的操作,而这些操作在程序指令的严格串行顺序处理过程中是不会发生的,并且会通过隐蔽的渠道将受害者的机密信息泄露给对手。我们首先描述变异,利用条件错误(第四部分),然后变异,利用了目标的间接分支(V)节。在大多数情况下,攻击从一个设置阶段开始,在这个阶段中,对手执行的操作会使处理器失效,这样它以后就会利用错误的推测性预测。此外,设置阶段通常包括一些步骤,这些步骤有助于诱导推测性的执行,例如操作缓存状态以删除处理器确定实际控制流所需的数据。在设置阶段,对手也可以准备隐蔽通道,用于提取受害者的信息,例如,通过执行冲洗或驱逐部分的Flush+Reload or Evict+Reload attack。
在第二阶段,处理器推测性地执行指令,将机密信息从受害者上下文中传输到一个微结构的隐蔽通道。这可能是由攻击者请求受害者执行操作触发的,例如,通过系统调用、套接字或文件。在其他情况下,攻击者可能利用自己代码的推测(误)执行来从同一进程获取敏感信息。例如,被解释器、实时编译器或“安全”语言沙箱化的攻击代码可能希望读取它不应该访问的内存。虽然推测性执行可能通过广泛的隐蔽通道公开敏感数据,但是给出的示例导致推测性执行首先读取攻击者选择的地址上的内存值,然后执行修改缓存状态的内存操作(以公开该值的方式)。
在最后阶段,恢复敏感数据。对于使用Flush+Reload或Evict+Reload的Spectre攻击,恢复过程包括定时访问被监视的高速缓存线路中的内存地址。Spectre攻击只假设推测执行的指令可以从内存中读取,而受害进程可以正常访问,例如,不会触发页面错误或异常。因此,Spectre与Meltdown[47]是正交的,它利用一些cpu允许用户指令无序执行的场景来读取内核内存。因此,即使处理器阻止用户进程中指令的投机性执行来访问内核内存,Spectre攻击仍然可以工作[17]。

IV. VARIANT 1: EXPLOITING CONDITIONAL BRANCH MISPREDICTION

在本节中,我们将演示攻击者如何利用条件转移错误预测从另一个上下文(例如另一个进程)读取任意内存。考虑这样一种情况,Listing1中的代码是一个函数(例如,一个系统调用或一个库)的一部分,该函数从一个不可信的源接收一个无符号整数x。运行该代码的进程可以访问大小为array1_size的无符号字节数组array1和大小为1mb的第二个字节数组array2。
在这里插入图片描述
代码片段以对x的边界检查开始,这对安全性至关重要。特别是,这种检查防止处理器读取array1之外的敏感内存。否则,超出边界的输入x可能触发异常,或者通过提供x =(要读取的秘密字节的地址)- (array1的基本地址),导致处理器访问敏感内存。
图1演示了结合推测性执行的边界检查的四种情况。在知道边界检查的结果之前,CPU通过预测比较的最可能结果来推测性地执行符合条件的代码。有很多原因可以解释为什么边界检查的结果不能立即知道,例如,在边界检查之前或期间的缓存丢失,边界检查所需执行单元的拥塞,复杂的算术依赖关系,或嵌套的推测性执行。然而,正如所示,在这些情况下,对条件的正确预测将导致更快的整体执行。
不幸的是,在投机执行期间,边界检查的条件分支可能遵循错误的路径。在这个例子中,假设一个对手使得代码运行如下:
•x的值是恶意选择的(越界),比如array1[x]解析为受害者内存中的某个秘密字节k;
•array1_size和array2未被缓存,但k被缓存;
•以前的操作接收到的x值是有效的,这导致分支预测器假设if可能为真。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值