Spectre Attacks: Exploiting Speculative Execution. 2019

来源

P. Kocher et al., “Spectre Attacks: Exploiting Speculative Execution,” 2019 IEEE Symposium on Security and Privacy (SP), 2019, pp. 1-19, doi: 10.1109/SP.2019.00002.

梳理

摘要

现代处理器依赖分支预测和推测执行来最大化性能。如果分支预测的目标依赖于需要在进程中读取的内存值,cpu就会猜测目标提前执行。在后续得到实际内存值时,CPU再交付/丢弃推测执行部分。推测逻辑能访问受害者memory和register,并且可以执行一些有害操作。
幽灵攻击:受害者推测性执行在正确的程序执行中不会发生的操作->侧信道泄露机密信息。
本文表明,结合一些实际攻击,如侧信道攻击、故障攻击、返回导向编程,能够读取受害者进程任意信息。推测执行实现违反了支持软件安全机制的安全假设,包括OS进程分离、容器化、JIT即时编译以及cache timing缓存时序攻击和侧信道攻击的对策。
虽然针对特定处理器的临时措施可能有效,但更合理的解决措施需要修复处理器设计并且更新ISA

I INTRODUCTION

物理侧信道攻击用于PC和移动设备。它们也面临的无需外部测量设备的软件攻击,一些基于软件漏洞,一些基于硬件漏洞(如微架构攻击:cache timing、branch prediction history、branch target buffer、open DRAM row)。
基于软件的技术也被也被用于安装故障攻击,从而改变物理内存和CPU值。

A. Our result

Spectre attack欺骗处理器预测性地执行 在正确程序执行时不会执行的指令序列。由于这些指令对处理器状态的影响最终被恢复,因此称为transient instructions(瞬态指令)。通过影响预测执行的瞬态指令,能够泄露受害者内存地址空间的信息。利用瞬态指令序列从非特权本地代码可移植的JavaScript代码跨安全域泄露信息 。

  • 通过非特权本地代码攻击:构造一个包含其内存地址空间机密数据的简单攻击程序->从受害者地址空间读取内存
  • 通过JS和eBPF攻击:本地代码违反进程隔离边界,幽灵还可通过违反沙箱进行攻击,如通过可移植JS代码挂载。实现一个JS程序能够从运行它的浏览器进程程序的地址空间读取数据。此外,还演示了在Linux中利用eBPF解释器和JIT进行攻击。

B. Our Techniques

幽灵攻击违反存储器隔离边界。1.在进程地址空间引入/定位指令序列,在被执行时,作为隐蔽信道发射器泄露受害者内存和寄存器内容;2.攻击者欺骗CPU以推测并错误执行这个指令序列;3.攻击者通过隐蔽通道检索受害者信息,虽然预测执行导致的CPU状态的更改最终会被恢复,但泄露的信息和对CPU的其他微架构状态的更改,如缓存内容,可以在流水线冲刷中存活。
诱导预测执行+微架构隐蔽信道。本文的实现基于cache-based隐蔽通道,如Flush+Reload,Evict+Reload。

Variant 1: Exploiting Conditional Branches

诱导CPU分支预测器错误预测分支方向,攻击者读取存储在程序地址空间的保密信息。
x包含了攻击者控制的数据。为确保对array1内存访问的有效性,上述代码包括含一个if语句用于检验x是否在合法范围。我们将展示攻击者如何绕过if语句 ,从进程的地址空间读取潜在的秘密数据。
在这里插入图片描述

  • 初始错误约束阶段:使用有效输入训练预测器。
  • 利用阶段:输入数组array1边界外的x,CPU预测边界检查为真,并使用恶意x推测执行array2[array1[x]*4096]。注意:从array2读取数据需要使用依赖array[x]扩展的地址从cache加载数据,扩展后可以访问cache的不同行以避免硬件预取的影响。
  • 边界检查后CPU恢复状态,但对cache的修改不会恢复,攻击者可以分析cache内容,并从内存中读取的越界数据中检索到潜在的秘密字节值。
Variant 2: Exploiting Indirect Branches

利用间接分支。攻击者从受害者地址空间中选择gadget并影响受害者预测性的执行该gadget。与ROP不同,攻击者不依赖代码中的漏洞。相反,攻击者训练BTB使间接分支指令错误预测到gadget地址,从而执行gadget。gadget能够从cache侧通道泄露敏感信息。论文展示了如何选择gadget以读取任意内存的方法。

  • 训练BTB:攻击者在受害者地址空间找到gadget,对该地址执行间接分支。
  • 训练在攻击者地址空间完成,攻击者地址空间中gadget地址包含了什么并不重要。重要的是:训练期间攻击者和受害者的虚拟地址匹配。事实上,只要攻击者处理异常,即使攻击者地址空间的gadget的虚拟地址没有映射代码,攻击也能生效。
Other Variants

通过改变预测执行实现方法泄露信息的方法可以设计进一步攻击。如:返回指令错误、从时间变化泄露信息、对算术单元的争用。

C. Targeted Hardware and Current Status

硬件:一些Intel处理器、AMD Ryzen芯片、基于ARM芯片的Samsung和Qualcomm处理器。
幽灵攻击:CVE-2017-5753(Spectre v1)、CVE-2017-5715(Spectre v2)。

II. BACKGROUND

A. Out-of-order Execution

顺序发射、乱序执行、顺序提交(commit)
乱序执行:指令被译码为微操作,指令对应的微操作和全面的指令全部完成,指令就能退出,将其更改交付到寄存器和其他架构状态,并释放ROB空间。因此,指令按程序执行顺序退出。为了保证代码执行的正确性,任何通过预测执行的指令,都需要按照程序原有的指令顺序交付,结合流水线刷新和丢弃受到错误预测影响的指令结果,就能保证即使是乱序执行的程序,最终的运行结果也与顺序执行的一致。

B. Speculative Execution

预测时保存寄存器状态。正确则交付,错误则恢复寄存器状态并放弃推测执行的工作。但瞬态指令带来的微架构影响保留。ROB决定了预测执行的指令数目。

C. Branch Prediction

现代处理器包含多个直接和间接分支的预测机制。间接分支指令可以在运行时跳转到任意目标地址。如x86指令能够跳转到寄存器、内存、或堆栈中的地址,"jmp eax"和"ret”。ARM、MIPS、RISC-V(jalr x0,x1,0)和其他处理器也支持间接分支。为了补偿与直接分支相比额外的灵活性,间接跳转和调用使用至少两个不同的预测机制进行了优化

一些处理器组件被用于预测分支结果。BTB(Branch Target Buffer)保存最近执行的branch指令的地址和目标地址。处理器可以在decode前使用BTB进行预测。

  • 条件分支的条件在运行中确定,因此没有必要记录跳转地址,为了改进预测,处理器维护最近的直接和间接分支的分支结果记录,即taken/not taken
  • ret指令是一种间接branch,现代CPU使用单独机制。RSB(Return Stack Buffer)维护近期调用堆栈的副本。若RSB中无可用数据,不同的处理器会选择停止执行或使用BTB回退。

D. The Memory Hierarchy

cache将内存分为固定大小的行,通常64或128字节。处理器从内存获取数据首先查询L1 cache是否有副本。一旦读完成,数据被存入cache,以防不久后使用。现代处理器通常有三级cache,L1和L2以及所有核共享的L3( Last-Level Cache,LLC)。

高速缓存一致性协议:有时被滥用,作为刷新或驱逐指令来代替缓存驱逐。这种行为在以前被研究用于帮助发起Rowhammer攻击
处理器基于MESI协议保证L1和L2 cache数据一致。缓存行跳跃(cache-line bouncing):一个核的内存写操作将导致其他核的L1或L2 cache被标记为不可用,即其他核无法通过L1和L2 cache加载该数据。若这一情况反复出现在特定位置,称为cache-line bouncing。false sharing:内存以行为粒度,即使两个核访问映射同一cache行不同位置的相邻内存,也会发生上述情况。带来性能问题。

E. Microarchitectural Side-Channel Attacks

当多个程序在同一硬件上执行时,无论并发还是分时共享,引起的微架构状态的变化可能会影响其他程序。这反过来可能会导致意外的信息从一个程序泄漏到另一个。

最初的微架构侧信道攻击利用L1 data cache的时间差异和泄露,从加密原语中提取密钥[52,55,69]。多年来,侧信道已经在多个微架构组件上演示,包括指令cache[3],较低级别cache[30,38,48,74],BTB[14,44],分支历史[1,2]。攻击的目标已经扩展到co-location detection[59],打破ASLR[14,26,72],击键监测[25]、网络指纹[51]、基因组处理[10]。近期的研究成果包括跨-core和跨-CPU攻击[37,75]、基于云的攻击[32,76],对可信执行环境的攻击[10,44,61],来自移动代码的攻击[23,46,51]以及新的攻击技术[11,28,44]。

本文:利用Flush+ReloadEvict+Reload泄露敏感信息。攻击者首先从与受害者共享的cache中驱逐一条cache line->受害者执行一段时间后,攻击者测量在被驱逐行对应的地址上执行memory read所花费的时间->如果受害者访问了被监控的cache line,数据将会在cache中,并且访问很快。否则,如果受害者没有访问该行,读取速度会很慢,因此通过测量访问时间,攻击者了解受害者是否在驱逐和探测步骤之间访问了被监控的cache line。
两种技术的区别:都是将被监控cache line从cache中驱逐出来的机制。Flush+Reload中,攻击者使用专用的机器指令,如x86的cflush来驱逐行。Evict+Reload中,在cache line中强制争用实现驱逐,如访问加载到cache中的其他内存位置(cache大小有限),导致处理器丢弃(驱逐)需要监控的行。

F. Return-Oriented Programming

ROP:返回导向编程是一种技术,允许攻击者劫持控制流,通过将机器代码片段链接在一起(即gadget,在受害者的代码中找到)执行复杂操作。
攻击者首先在受害者二进制文件中查找可用gadget。每一个garget在返回指令前执行一些计算。攻击者可以修改堆栈指针,如指向返回外部可写buffer的地址,或覆盖堆栈内容,如利用缓冲区溢出使堆栈指针指向一系列恶意选择的gadget地址.。在执行时,每个return指令跳转到堆栈中的目的地址。因为攻击者控制这一系列地址,每个return 有效地跳转到了链中下一个gadget。

III. ATTACK OVERVIEW

设置阶段:攻击者执行操作使处理器出错,以便后续做出错误预测。

  • 帮助诱导预测执行,如操纵cache状态移除处理器确定实际控制流所需的数据。
  • 准备用于提取受害者信息的隐蔽通道,如执行flush和evict部分的操作。

第二阶段:处理器预测执行指令,将机密信息从上下文传输到隐蔽通道。

  • 攻击者请求受害者执行一个操作触发,如,系统调用,socket,文件。
  • 攻击者利用自己代码的预测执行从同一进程获得敏感信息。如,被解释器、JIT、安全语言沙箱化的攻击代码可能希望读取它不应该访问的内存。

最后阶段:恢复敏感数据。

  • 对被监控cache line中的内存地址访问计时。

幽灵攻击假设预测执行指令能够读取 受害者进程可以正常访问的内存,如不触发页面错误或异常。熔断与幽灵正交,后者利用了一些CPU允许用户指令乱序执行来读取内核内存的场景。因此,即使处理器阻止用户的指令预测执行以访问内核内存,幽灵攻击仍然生效。

IV. VARIANT 1: EXPLOITING CONDITIONAL BRANCH MISPREDICTION

Spectre V1 理论与实践

实验显示高准确率,可能的错误原因:

  • 发现一个内存空间是否被存入cache的方法通常是时间度量,其精度有限(如JS或许多ARM平台中)。因此,可能需要多次攻击迭代来获取可靠结论。
  • 如果数字array2元素意外缓存,如由于硬件处理、操作系统活动或其他内存访问进程(如,如果数组2对应于其他进程正在使用的共享库中的内存),也有可能发生错误。攻击者可以重新执行攻击传递,使得array2中没有元素/两个以上元素被缓存。这种简单的重复标准和基于rdtscp的精确计时进行的测试,在Intel Skylake和Kaby Lake处理器上的错误率约为0.005%。

V. VARIANT 2: POISONING INDIRECT BRANCHES

B. Indirect Branch Poisoning Proof-of-Concept on Windows

Spectre V2 理论与实践
ASLR(Address space layout randomization)是一种针对缓冲区溢出的安全保护技术,通过对堆、栈、共享库映射等线性区布局的随机化,通过增加攻击者预测目的地址的难度,防止攻击者直接定位攻击代码位置,达到阻止溢出攻击的目的。
指令sbb eax,[esp+ebx]用于定位栈的gadget。Win32的ALSR仅改变少量地址位,因此只需要尝试一些组合来找到在受害者进程上有效的序列。

C. Reverse-Engineering Branch Prediction Internals

通过逆向工程复原Intel处理器的direct jump的预测方式,以及BHB的结构
分支预测器的碰撞:可被利用来分析预测器的精确函数。

VI. VARIATIONS

Spectre variant 4: 在存储到加载转发逻辑(store-to-load forwarding logic)使用了预测执行。处理器推测load不依赖与先前store。

Evict+Time:测量依赖于cache状态的操作所学的时间来实现攻击。

Instruction Timing:Spectre的攻击不一定必须涉及cache。在时间上依赖于操作数值的指令可能会泄露操作数的信息。如:预测执行multiply R1,R2。乘法器对于multiply R3,R4可用的时间可能被第一次乘法影响(无论是乱序执行还是错误预测被识别)。泄露R1和R2的信息。
在这里插入图片描述
Contention on the Register File:假设reg file中由有限个可用reg用于存储预测执行检查点,多个连续预测执行创建多个检查点。若由于缺少预测存储空间导致预测执行减少,会泄露R1的信息。
在这里插入图片描述

Variations on Speculative Execution:预测执行的变体:不包含condition branch的代码也有潜在风险。考虑:攻击者希望确定R1是否包含攻击者选择的值V或其他值->足以破坏一些加密实现。方法:mistrain使中断后返回所需的read memory [R1]指令。

Leveraging Arbitrary Observable Effects:考虑Spectre V1示例中预测执行不能改变Cache。array2的推测查找仍然发生,其时间受cache状态的影响,仍会影响后续推测操作的深度和时间。在推测执行前修改cache状态,攻击者可以潜在的利用推测执行所产生的任何可观察的影响。如使用y做一些推测执行可观测到的操作。在这里插入图片描述

VII. MITIGATION OPTIONS

A. Preventing Speculative Execution

  • 使用序列化或推测阻塞指令确保其后的指令不会被推测执行,如lfence。=>显著降低性能
  • 使用静态分析减少所需的推测阻塞指令,因为许多代码没有读取和泄露out-of-bound memory的能力。
  • MSVC(Microsoft’s C compiler MSVC)将未检测到已知的错误模式的代码设置为无需保护代码,但会遗漏很多错误模式。
  • 间接分支前插入lfence指令可以确保先前的流水线被清空,帮助缓解分支中毒。=>要求检测所有潜在的易受攻击的软件,需要更新软件二进制文件和库。

B. Preventing Access to Secret Data

  • 在一个单独的进程中执行每一个网站,因为幽灵攻击需要利用受害者的访问权限。
  • 使用索引掩码代替边界检查。=>可能带来数组边界之外的访问,但限制了距离,防止任意内存访问。
  • 通过使用伪随机poison值来保护对指针的访问。

C. Preventing Data from Entering Covert Channels

处理器跟踪数据是否被预测操作获取,如果是,则防止这些数据在可能泄露的后续操作中被使用。=>然而目前的处理器没有这种功能

D. Limiting Data Extraction from Covert Channels

减少隐蔽通道:降低计时器分辨率,禁用共享缓冲区(防止用于创建计时源)

E. Preventing Branch Poisoning

  • 扩展控制间接分支机制的ISA,由三个组件构成:IBRS(间接分支限制推测)、STIBP(单线程间接分支预测)、IBPB(间接分支预测屏障)。
  • retpolines:用return指令替换间接分支的代码序列。该构造确保return指令通过返回堆栈缓冲区RSB被预测为良性无限循环,通过将实际目标目的地推入堆栈并返回到它来到达实际目地。

VIII. CONCLUSIONS

Spectre attack是实用的,无需任何软件漏洞,允许攻击者从其他进程和安全上下文中读取私有内存和寄存内容。
长期的解决方案:需要从根本上改变指令集架构
处理器设计时间面临着性能与安全性的权衡。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值