3.12 微体系结构侧信道攻击
本章介绍的推测执行和多线程技术,使宽发射处理器能够在广泛的工作负载上取得良好性能。但这些技术也引入了一类新的安全漏洞,称为微体系结构侧信道攻击,或瞬态执行攻击(transient execution attacks)。从 Meltdown[Lipp 等,2018]和 Spectre[Kocher 等,2019]攻击问世以来,新的侧信道攻击类型及变体不断出现。它们利用超标量处理器的性能机制,访问并泄露秘密数据。
微体系结构侧信道攻击,与第 2 章介绍的 prime-probe 攻击相似。特别令人担忧的是,这类攻击允许窥探者控制 prime 与 probe 两个阶段之间执行的指令序列。下面将解释,推测如何让这些指令绕过软件边界检查、虚拟内存保护、虚拟机隔离以及可信执行的硬件隔离等安全机制,直接访问秘密数据。因此,它们能够快速、准确地在缓存中留下标记,供探测阶段观察。更糟的是,SMT 处理器允许窥探进程与受害进程共享处理器流水线。这带来两个问题。第一,窥探者可以利用一级缓存、BTB 等多种缓存结构,建立高带宽侧信道。第二,由于窥探者与受害者并行运行,窥探者能够在正常执行活动(例如缓存重新填充)覆盖泄露的信息之前,迅速探测侧信道。推测与 SMT 相结合,使侧信道攻击在准确性和有效带宽方面,有可能超过此前所有已知攻击。大量服务运行在公有云框架等共享基础设施上,而这些设施采用超标量与 SMT 处理器,因此,微体系结构侧信道攻击可能带来严重的安全影响。
下面用一段概括最初 Meltdown 攻击的伪代码,说明推测如何协助侧信道攻击[Lipp 等,2018]。在共享核心上运行这段代码的窥探者,有可能观察到操作系统内核所使用的任意内存地址的值。
译注:原书分配及后文说明使用
user_memory,最后一条伪代码却使用user_array。注释的位置也沿用原页,不据此将代码视为完整可执行实现。
窥探者首先准备系统:(1)分配数组 user_memory;(2)确保其所有元素都不在处理器一级缓存中。接着,(3)发射一条会产生异常的指令,例如算术异常(除以零),或由加载指令触发的内存保护错误。如果处理器一次只执行一条指令,那么后续步骤(4~6)都不会执行。但支持推测的处理器会继续执行后面的代码,直到产生异常的指令到达 ROB 队首。因此,在异常被触发、步骤 4~6 的指令结果被丢弃之前,后续所有指令很可能已经完整或部分执行。
下一条指令(4)访问一处本不应有权访问的内核内存位置,例如,给窥探者地址空间中的指针加上或减去一个较大的偏移量。指令(5)依据读出的内核内存值的最低有效位,生成索引值 0 或 256;指令(6)用这个索引读取 user_memory 数组中的一个元素。异常到达 ROB 队首时,指令(4~6)会被撤销,但指令(6)对处理器一级缓存产生的影响仍然保留:数组 user_memory 的一部分已经进入缓存。窥探者可以在异常恢复后,或者在同一 SMT 处理器的另一个并行线程中,通过测量访问 user_memory 各元素的耗时来探测缓存。如果元素 0 的加载很快,说明缓存命中,也就说明该内核内存位置的最低有效位为 0;如果元素 256 的加载很快,则最低有效位为 1。窥探者可以重复这些步骤,绕过虚拟内存保护,逐步读取大片内核内存及其中的全部秘密。Meltdown 论文详细解释了各个步骤,并展示了 x86 指令集上的实现[Lipp 等,2018]。
大多数微体系结构侧信道攻击的结构都与 Meltdown 相似。在准备与探测之间,窥探者利用推测执行一些访问、泄露秘密数据的指令,但不让它们提交。秘密数据用于改变某个硬件性能机制的状态,随后再探测该机制,以推断秘密数据的若干位。近期提出的攻击使用了超标量处理器中广泛的性能机制(缓存、BTB 等)或推测事件(延迟异常报告、分支预测、内存消歧)。在包括 Spectre 在内的许多攻击中,窥探者通过现有软件接口调用操作系统或受害进程,并精心选择输入,使受害者自身的代码以推测方式访问、泄露秘密数据。受害进程处理这个调用时,窥探进程利用同一核心上的 SMT 线程探测泄露的数据。关于微体系结构侧信道攻击的详细回顾与分类,可参阅 Guangyuan Hu 等的综述[Hu 等,2021]。
在不损失性能的前提下,很难防御微体系结构侧信道攻击。第一种防御方式,是重新编译并修改可能操作秘密数据的代码。编译器可以加入 fence 指令,在某个条件确定之前,禁止推测执行。另一种做法是,在利用推测的指令与可能泄露秘密数据的加载之间,引入依赖;这称为推测加载加固(speculative load hardening)。这类防御的缺点在于依赖重新编译,而重新编译并非总是可行;另外,决定对潜在易受攻击代码多广泛地应用这些防御时,必须在性能与安全之间取舍。第二种方式,是限制对可用于传递秘密的共享硬件结构的访问。有些情况下会关闭 SMT 多线程,防止窥探进程轻易观察同一 SMT 处理器上与受害进程共享的各种结构。
通过缓存分区技术隔离不同进程使用的缓存空间,也能降低某些攻击的有效性。最后,还有若干方案提出修改处理器流水线,在推测期间限制访问或推迟使用潜在敏感数据,或者撤销错误推测指令对硬件性能机制的影响。Guangyuan Hu 等的综述也回顾了微体系结构侧信道攻击防御的主要类别[Hu 等,2021]。截至本书写作时,还没有一组防御措施能够保证应对所有可能的攻击。
微体系结构侧信道攻击使人们意识到:现有 ISA 对正确行为的规定,并不足以支持对安全攻击的推理。ISA 以独立于时序的方式,定义可编程处理器的功能行为。因此,完全可能构建出正确实现 ISA、却容易受到安全攻击的超标量处理器。当前的推测式超标量处理器正存在这一弱点。本领域还缺少相应的抽象与工具,用于建模并形式化分析硬件实现的时序行为,如何与安全和隐私意义上的正确执行相互作用。截至本书写作时,已有若干研究工作在应对这一挑战。