导语:2018年1月,微软发布​了一项针对新一类硬件漏洞的建议和安全更新,这些漏洞(Meltdown和Spectre)涉及到预测执行边信道 (speculative execution side channel)。在本文中,我将提供一种新的预测执行边信道漏洞的技术分析。

2018年1月,微软发布了一项针对新一类硬件漏洞的建议和安全更新,这些漏洞(Meltdown和Spectre)涉及到预测执行边信道 (speculative execution side channel)。在本文中,我将提供一种新的预测执行边信道漏洞的技术分析,这种漏洞被称为“L1终端故障”(L1 Terminal Fault),简称L1TF。

这篇文章主要面向对L1TF技术分析以及与L1TF相关的缓解措施感兴趣的安全研究人员和工程师。

L1终端故障(L1TF)概述

L1TF是一种最近发现的预测执行侧信道分析的安全漏洞,会影响一部分支持Intel SGX软件保护扩展的处理器,包括自第二代酷睿(Sandy Bridge)以来的各类桌面、移动笔记本、服务器和数据中心产品。

该漏洞由鲁汶大学、以色列理工学院、密歇根大学、阿德莱德大学、Data61的研究人员首次发现并向Intel报告。

Intel进一步研究后发现,L1TF漏洞的另外两种相关应用还存在影响其它处理器、操作系统和虚拟化软件的可能。具体来说就是:

· CVE-2018-3615:影响英特尔的软件保护扩展(SGX);

· CVE-2018-3620:影响操作系统和系统管理模式(SMM);

· CVE-2018-3646:影响虚拟化软件和虚拟机监视器(VMM);

我之前定义了四种类型的预测基元(speculation primitives),它们可以为预测执行边信道创建条件。每个类型都提供了沿着非体系结构路径进入预测执行的基本方法,已经发现的可用于预测执行边信道攻击的分支主要有四种:条件分支错误预测(conditional branch misprediction)、间接分支错误预测(indirect branch misprediction)、传送异常或延迟((exception deliveryor deferral))以及内存访问错误预测(memory access misprediction)。L1TF属于预测基元的传送异常或延迟类型(以及Meltdown和Lazy FP状态恢复),因为它处理与生成架构异常的逻辑相关的预测(或无序)执行。所以,在本文中,我将提供L1TF的概要,有关更深入的分析,请参阅英特尔针对这一漏洞发布的咨询和白皮书

L1TF的出现是由于在执行页表遍历时,与地址转换处理相关的CPU优化。在转换线性地址时,CPU可能会遇到终端页面故障,当虚拟地址的分页结构条目不存在(当前位为0)或无效时,就会出现这种故障。这将导致异常,例如页面错误,或TSX事务沿体系结构路径中止。然而,在这两种情况发生之前,容易受到L1TF攻击的CPU可能会从L1数据缓存中发起对正在转换的线性地址的读取。对于这种仅用于预测的读取,终端(不存在)页表条目的页帧位被视为系统物理地址,甚至对于客户页表(guest page table)条目也是如此。如果物理地址的缓存行存在于L1数据缓存中,那么这条行的数据可能会被转发到相关的操作,这些操作可能会在导致终端页面错误的指令退出之前进行预测性的执行,与L1TF相关的行为可以发生在涉及常规和扩展页表(后者用于虚拟化)的页表遍历中。

为了说明这是如何发生的,我特意举了一个简化样本。在本例中,攻击者控制的虚拟机(VM)在VM中构建了一个页表层次结构,目的是读取所需的系统(主机)物理地址。下图为虚拟地址0x12345000提供了一个层次结构样本虽然终端页表项不存在但包含页框架0x9a0,如下所示。

1.png

在建立了这个层次结构之后,VM可以尝试通过以下指令序列从[0x9a0000, 0x9a1000]中的系统物理地址读取。

01: 4C0FB600          movzx r8,byte [rax] ; rax = 0x12345040
02: 49C1E00C          shl r8,byte 0xc
03: 428B0402          mov eax,[rdx+r8]    ; rdx = address of signal array

通过在TSX事务中执行这些指令或通过处理架构页面错误,VM可以尝试从与系统物理地址0x9a0040相关联的L1数据缓存行(如果存在于L1中)引起预测性加载,其中第一个字节的缓存行会变成一个无序的负载,该负载使用第一个字节作为信号数组的偏移量。这将为使用诸如FLUSH+RELOAD这样的公开基元观察字节值创造条件,从而导致在没有将系统物理地址分配给VM的情况下跨安全边界公开信息。

虽然上述场景为大家介绍了L1TF如何应用于跨虚拟机边界预测物理内存(虚拟机完全控制客户页表),但在其他场景中也可以使用L1TF。例如,用户模式应用程序可以尝试使用L1TF从物理地址中读取,这些物理地址是通过在它们自己的地址空间中不存在终端页表条目引用的。实际上,操作系统通常使用非当前页表条目格式中的软件位( software bits)来存储元数据,这可能等同于有效的物理页帧。这可能允许进程读取未分配给进程的物理内存(或虚拟场景中的VM)或进程中不打算访问的物理内存(例如Windows上的PAGE_NOACCESS内存)。

L1终端故障(L1TF)的缓解措施

目前,L1TF有多种缓解措施,它们会根据被缓解的攻击类型有所区别。为了说明这一点,我将描述存在L1TF风险的软件安全模型以及可用于缓解它的具体策略。其中,我会用到上一篇中所讲到的缓解预测执行边信道的几种缓解分类法

软件安全模型

下表总结了L1TF与软件安全模型通常关注的各种设备内部攻击场景的潜在相关性,与只影响用户场景内核的Meltdown (CVE-2017-5754)不同,L1TF适用于所有由橙色单元表示的设备内部攻击场景(灰色单元表示不适用),这是因为L1TF可以提供读取任意系统物理内存的能力。

3.jpg

防止涉及L1TF的预测技术

正如我过去所指出的那样,缓解漏洞的最佳方法之一是尽可能地从根源解决问题。对于L1TF来说,我们可以使用多种缓解措施来防止涉及L1TF的预测技术。

不显示页表条目的安全页帧位

要实现L1TF的攻击,其中一个要求就是终端页表条目的页帧位必须引用包含来自另一个安全域的敏感数据的有效物理页。这意味着,通过兼容的管理程序和操作系统内核是可以缓解某些攻击场景的,比如:

1. 确保由不存在的页表条目的页帧位引用的物理页总是包含良性数据;

2. 通过高阶来缓解L1TF的某些攻击情形,原理就是在页面帧位中设置了与可访问物理内存不对应的位。

在方法2时,Windows内核将使用比给定处理器支持的物理地址位少的位,以避免物理地址截断(例如删除高阶位)。

26: kd> !pte 0x00000281`d84c0000
…   PTE at FFFFB30140EC2600
…   contains 0000000356CDEB00
…   not valid
…    Transition: 356cde…    Protect: 18 - No Access

26: kd> dt nt!HARDWARE_PTE FFFFB30140EC2600
+0x000 Valid : 0y0
+0x000 Write : 0y0
+0x000 Owner : 0y0
+0x000 WriteThrough : 0y0
+0x000 CacheDisable : 0y0
+0x000 Accessed : 0y0
+0x000 Dirty : 0y0
+0x000 LargePage : 0y0
+0x000 Global : 0y1
+0x000 CopyOnWrite : 0y1
+0x000 Prototype : 0y0
+0x000 reserved0 : 0y1
+0x000 PageFrameNumber : 0y000000000000001101010110110011011110 (0x356cde)
+0x000 reserved1 : 0y0000
+0x000 SoftwareWsIndex : 0y00000000000 (0)
+0x000 NoExecute : 0y0

从2018年8月的Windows安全更新开始,所有支持的Windows内核版本和Hyper-V虚拟机监控程序都确保在容易受到L1TF攻击的硬件上自动执行方法1和方法2。这对于传统页表条目和不存在的扩展页表条目都是强制执行的。在Windows Server上,默认情况下禁用此缓解措施,必须按照我发布的Windows Server指南中的说明启用此缓解。

为了说明这是如何工作的,我特意举了下面的一个使用用户模式虚拟地址的案例,由于它是不可访问的,因此没有呈现PTE。

通过应用2018年8月的Windows安全更新,可以观察到在不存在的页表条目中设置高阶位的行为,该条目指的是无法访问或保证是良性的物理内存(在本例中为第45位)。由于这与可访问的物理地址不对应,因此任何使用L1TF从其读取的尝试都将失败。

17: kd> !pte  0x00000196`04840000
…   PTE at FFFF8000CB024200
…   contains 0000200129CB2B00
…   not valid
…    Transition: 200129cb2
…    Protect: 18 - No Access

17: kd> dt nt!HARDWARE_PTE FFFF8000CB024200
+0x000 Valid            : 0y0
+0x000 Write            : 0y0
+0x000 Owner            : 0y0
+0x000 WriteThrough     : 0y0
+0x000 CacheDisable     : 0y0
+0x000 Accessed         : 0y0
+0x000 Dirty            : 0y0
+0x000 LargePage        : 0y0
+0x000 Global           : 0y1
+0x000 CopyOnWrite      : 0y1
+0x000 Prototype        : 0y0
+0x000 reserved0        : 0y1
+0x000 PageFrameNumber  : 0y001000000000000100101001110010110010 (0x200129cb2)
+0x000 reserved1        : 0y0000
+0x000 SoftwareWsIndex  : 0y00000000000 (0)
+0x000 NoExecute        : 0y0

为了提供一种可移植的方法,允许VM确定系统上支持的实现的物理地址位,Hyper-V管理程序顶级功能规范(Hyper-V hypervisor Top-Level Functional Specification ,TLFS) 已经使用可由VM使用的已定义接口进行了修订,VM可以使用这个接口来查询这些信息,这有助于在迁移池中安全迁移虚拟机。

在安全域转换时刷新L1数据缓存

通过使用L1TF披露的信息需要来自受害者安全域的敏感数据出现在L1数据缓存中(注意,L1D由同一物理内核上的所有LP共享)。这意味着可以通过在安全域之间转换时刷新L1数据缓存来防止信息泄露。为了实现这一点,Intel通过微代码更新提供了新的功能,该微代码更新支持用于刷新L1数据缓存的体系结构接口。

从2018年8月Windows安全更新开始,Hyper-V管理程序顶级功能规范现在使用新的L1数据缓存刷新功能,以确保在关键时刻将VM数据从L1数据缓存中删除。在Windows Server 2016以上和Windows 10 1607以上的版本中,当在vm之间切换虚拟处理器上下文时发生刷新。这有助于通过最小化需要执行刷新的次数来减少刷新对性能的影响。在以前的Windows版本中,刷新发生在执行VM之前(例如VMENTRY之前)。

为了使Hyper-V虚拟机监控程序中的L1数据缓存刷新更加有效,刷新是与安全使用或禁用超线程和每个虚拟处理器虚拟机监控程序地址空间相结合进行的。

对于SGX enclave来说,Intel提供的微代码更新可以确保逻辑处理器退出enclave执行模式时,L1数据缓存被刷新。微代码更新还支持BIOS是否启用HT的验证,当启用HT时,在刷新或清除L1数据缓存中的enclave机密之前,有可能有来自同级逻辑处理器( sibling logical processor )的L1TF攻击。如果验证认证的实体认为来自同级逻辑处理器的L1TF攻击的风险不可接受,那么它可以拒绝支持HT的系统的认证。

安全调度同级逻辑处理器

英特尔的超线程(HyperThreading, HT)技术,也称为同步多线程(concurrent multithreading, SMT),允许多个逻辑处理器在一个物理内核上同时执行。每个同级LP都可以在不同的安全域和特权模式下同时执行代码。例如,一个LP可以在管理程序中执行,而另一个LP则可以在VM中执行代码。这对L1数据缓存刷新有影响,因为在L1数据缓存刷新发生后,敏感数据可能会通过同级LP重新进入L1数据缓存。

为了防止这种情况发生,必须安全的调度同级节点上的代码执行,或者必须禁用HT。这两种方法都可以确保内核的L1数据缓存不会在刷新发生后被来自另一个安全域的数据污染。

Windows Server 2016及更高版本上的Hyper-V管理程序支持一个被称为内核调度程序的功能,该功能确保在物理内核上执行的虚拟处理器始终属于同一个VM,并被VM描述为同级超线程。此功能需要管理员选择加入Windows Server 2016,默认情况下从Windows Server 2019开始启用。它与每个虚拟处理器虚拟机监控程序地址空间相结合,使得将L1数据缓存刷新延迟到内核从不同VM开始执行虚拟处理器的时间点成为可能,而不需要在每个虚拟机上执行刷新。

下图说明了具有两个不同VM(VM 1和VM 2)的方案的虚拟处理器调度策略的差异,如下图所示,在没有启用内核调度的情况下,来自两个不同VM的代码可以在内核上同时执行,而在启用内核调度时这是不可能的。

img2.png

在Windows Server 2016之前的Windows版本以及所有支持虚拟化的Windows客户端版本中,不支持内核调度程序功能,因此可能需要禁用HT,以确保L1数据缓存刷新在VM隔离中的有效性。当禁用HT时,同级逻辑处理器不可能同时在同一物理内核上执行。

从内存中删除敏感内容

另一种减少预测执行边信道攻击的策略是将敏感内容从地址空间中删除,使其不能通过预测执行来公开。

分区每个vm地址空间

在预测执行边信道出现之前,虚拟机监控程序并不需要在每个vm的基础上分区它们的虚拟地址空间。因此,管理程序通常的做法是维护所有物理内存的虚拟映射以简化存储器访问。 但由于L1TF和其他预测性执行端通道的存在,使得在虚拟机监控程序代表VM执行时,可以从虚拟机监控程序的虚拟地址空间中删除跨VM的秘密。

从2018年8月的安全更新开始,Windows Server 2016+和Windows 10 1607+中的Hyper-V hypervisor现在使用每个虚拟处理器(也就是每个vm)地址空间,并且不再将所有物理内存映射到hypervisor的虚拟地址空间。这确保在对给定虚拟处理器进行预测期间,仅能够访问代表VM分配给VM和hypervisor的内存。在L1TF的情况下,这种缓解工作结合L1数据缓存刷新和安全使用或禁用HT,以确保L1中没有敏感的跨vm信息可用。

总结

把前几节中描述的缓解措施结合使用,就可以为L1TF提供了全面的保护。下表总结了针对不同版本的Windows Server和Windows Client的攻击场景、缓措施解和默认设置的关键点。

360截图16240209103132145.jpg

简单地说,L1TF攻击场景与缓解措施之间的对应关系可以总结如下。

360截图165712315886100.jpg

在这篇文章中,我分析了一个新的预测执行边信道漏洞,即L1终端故障(L1TF),并对它的攻击原理和缓解方法做了整体描述。这种漏洞可以在多种攻击场景中发生,且相关的缓解措施需要结合各自受影响的英特尔处理器所对应的版本。

源链接

Hacking more

...