深入解析Spectre漏洞:V1与V2变种的技术原理与影响

本文详细解析了Spectre漏洞的两种变体(V1和V2),包括其利用分支预测错误和推测执行的技术原理,攻击步骤,以及对桌面用户和云服务商的严重影响,同时提供了缓解措施建议。

Spectre(变种1)

Spectre的第一个变体允许程序读取本不应访问的内存。Spectre V1攻击之所以可行,是因为分支预测和推测执行这两种优化的结合。Spectre V1攻击欺骗条件分支预测器跳过安全检查,并在错误的上下文中推测执行指令。这些推测执行指令的效果通过缓存计时侧信道可见。

技术细节

让我们通过一个假设的例子来逐步说明。尽管步骤看起来复杂,但通过JavaScript在Web浏览器中执行是完全可能的——参见Spectre论文中的工作概念验证。以下示例假设通过Web浏览器中的JavaScript传递Spectre攻击。这不是必须的。Spectre可以作用于各种程序,不仅仅是Web浏览器。此外,为简洁和清晰起见,省略了一些细节。

首先,我们将创建两个大的内存分配。一个称为leaker,另一个称为reader。在JavaScript中,这些可以通过ArrayBuffers创建,这是一种用于存储二进制数据(如图片)的结构。leaker分配将用于缓存计时侧信道。reader分配仅用于训练分支预测器。我们分配的数组具有固定长度。只有从零(第一个元素)开始到数组长度之前(最后一个元素)结束的数组项才是合法的读取范围。因此,对于一个256字节的数组,有效项编号为0到255。这个从第一个到最后一个元素的范围称为数组边界。

接下来,我们开始训练分支预测器。Spectre攻击依赖于修饰分支预测器,使其猜测某些安全检查总是通过。在这个具体案例中,我们将使分支预测器猜测从reader读取的值总是在边界内。JavaScript检查数组读取的边界;越界读取将失败并导致程序停止工作。数组边界(目前!)通过分支指令检查。对于Spectre攻击的这一部分,我们将重复从reader读取边界内的值。回想一下,处理器假设当前行为可以预测未来行为。如果分支总是被采取(或不采取),那么分支预测器将被训练为期望相同的行为。

接下来,我们确保leaker的任何部分都没有被缓存。这在JavaScript中也是可以做到的。为简洁起见,我们省略了细节。

现在准备工作已经完成,让我们进入Spectre V1漏洞的核心。我们将从reader读取一个越界元素。让我们称这个值为secret。因为我们从数组边界之外读取secret,根据定义,它可以是任何选定的内存位置。即使存在逻辑上阻止其发生的边界检查,secret的读取也会暂时成功。它之所以成功,仅仅是因为分支预测器已被预设为假设边界检查将通过。此时,处理器发现错误预测分支并取消执行错误预测指令的倒计时也开始。

接下来,我们使用secret的值作为索引从reader读取一个元素(即reader[secret])。这个操作将被推测执行,并导致reader的该元素被缓存。此时,分支预测器可以纠正自身并取消执行所有推测执行的指令。

通过测量读取secret每个元素的时间,可以确定哪个元素被缓存。被缓存元素的索引将是secret的值,即程序未被允许读取的值。例如,如果reader[42]被缓存,则secret的值为42。

现在可以重复攻击以读取更多字节。此信道的带宽估计为10 KB/s。

参见图2,了解步骤4中readersecret数据内存位置的图形表示。

图2: reader和一些秘密数据在计算机内存中的假设布局。由于计算机内存是线性布局的,可以通过reader的正或负索引访问其任何部分。对reader的访问应受其边界0到255的限制。如果边界检查被绕过,即使是通过一些推测执行的指令,也可能在没有适当权限的情况下访问内存。

影响是什么?

Spectre(变种1)对桌面、笔记本电脑和移动用户来说是一件大事。它让网站打破内置在Chrome、IE和Firefox等Web浏览器中的安全性和隔离保证。例如,Spectre可能允许在一个标签页中打开的网站读取您正在另一个标签页中输入的密码,或者允许结账页面上的广告读取您正在输入的信用卡号。

Spectre对云提供商和互联网公司同样具有毁灭性。许多驱动您喜爱网站的代码依赖于编程语言提供的隔离保证。Spectre将这些保证变成了良好的意图。应用程序托管提供商必须重新评估其安全架构,重建大量核心代码(伴随性能损失),或两者兼而有之。

对于变种1,没有通用的修复方法。受影响的软件必须重新编译以避免使用易受攻击的代码模式。然而,可以利用漏洞的利用变得更加困难。这是Web浏览器供应商目前采取的道路。他们移除了高分辨率计时器(确定某物是否被缓存所必需),并积极避免使用易受攻击的代码模式。

我该怎么办?

将您的浏览器、操作系统和BIOS更新到最新版本。所有浏览器供应商都已发布针对Spectre漏洞的缓解措施。

所有主要云提供商都已部署缓解措施。作为客户,您无需担心未来。

Spectre(变种2)

Spectre的第二个变体允许程序读取本不应访问的内存,无论该内存是同一程序的一部分、另一个程序的一部分,还是核心操作系统的一部分。

与Spectre V1一样,Spectre V2也依赖于滥用分支预测、推测执行和缓存计时侧信道。V1欺骗条件分支预测器,而V2欺骗间接分支预测器。间接分支预测器对权限更改漠不关心,包括从用户到内核、从程序到程序,甚至从虚拟机(考虑云计算实例)到管理程序(云控制平面)。由于这些原因,Spectre V2攻击可以发生在现代处理器提供的几乎所有权限级别上。

技术细节

在已发布的三种攻击中,Spectre V2攻击是最复杂的。为了解释Spectre V2攻击,我们将描述Google Project Zero博客中概述的简化版本。将省略许多技术细节,以期提供对攻击的更易理解的理解。

这里描述的Spectre V2攻击从客户虚拟机读取特权管理程序内存。Google Project Zero证明,这种攻击适用于在真实处理器上运行的真实软件。

首先,快速回顾一下间接分支和间接分支预测器。间接分支告诉处理器开始在某些新位置执行指令。这个位置可以存储在内存中。如果该位置未被缓存,处理器将不得不暂停很长时间(相对于指令执行速度)以等待找出获取指令的位置。间接分支预测器猜测处理器下一步将去哪里,因此处理器不必等待。如果猜测结果错误,处理器取消执行一些指令并返回正确的位置。如果猜测结果正确,程序运行速度会快得多。处理器非常擅长正确猜测,因此这通常会导致速度大幅提升。

是时候介绍第一个Spectre V2概念了:间接分支预测器通过将最近执行的分支历史保存在分支历史缓冲区(BHB)中工作,有时称为分支历史表,因为先前的分支决策通常指示未来的分支决策(图3)。与Meltdown和Spectre V1一样,通过仔细测量某些分支操作所需的时间,可以“读取”BHB并确定先前执行指令的位置——即使这些指令是在不同权限级别或不同程序中执行的。

图3: 分支历史缓冲区用于预测间接分支的目标,以便处理器可以更快地执行它们。当间接分支执行时,一个条目被写入表中。表空间有限,并根据分支地址索引。由于这种限制,可以“毒化”分支预测器,使其为任何间接分支猜测攻击者选择的地址。在这个假设的预测示例中,任何地址以045C结尾的分支都将具有相同的预测目标。

现在是第二个Spectre V2概念:分支预测器在处理器上运行的所有程序之间共享。在一个程序中执行的分支会改变间接分支预测器在另一个程序中的猜测方式。通过执行一系列精心选择的分支,您可以“写入”BHB,并强制分支预测器为您选择的未来间接分支猜测一个位置——即使该间接分支将在不同权限级别执行。这类似于Spectre V1,但使用间接分支而不是条件分支。

Google Project Zero的Spectre V2攻击描述的步骤不太详细,因为没有好的方法来压缩所需信息。下面描述的每个步骤都非常复杂且难以正确完成。描述的场景是云计算实例读取云控制平面(具体是Linux-KVM)的内存内容。该内存包含有关该物理机上所有其他云计算实例正在做什么的私人信息,包括用户私人数据、软件源代码、加密密钥等。

攻击准备

首先,分配一个大的内存块,将用于缓存计时侧信道。根据我们先前的约定,我们将此块称为reader

为了通过推测执行泄漏数据,我们需要某种方式强制管理程序首先读取一个特权内存字节,并使用该字节访问reader。这种代码模式可能很难找到,但幸运的是我们可以作弊。KVM管理程序是Linux内核的一部分,Linux内核包含一个运行自定义程序以快速处理网络流量的功能。此功能称为eBPF解释器。我们可以使用eBPF解释器在管理程序中创建我们需要的代码模式。为此,我们需要:

  • 在管理程序中找到eBPF解释器,并且
  • 向eBPF解释器提供一些代码,我们称之为ebpf_code

因为Spectre V2依赖于欺骗间接分支预测器,我们需要知道管理程序中间接分支的位置。我们称此分支为indirect_branch

管理程序对计算机内存的看法与我们在云实例中的程序不同。因为我们将从管理程序泄漏内存,我们需要找出readerebpf_codeindirect_branch和eBPF解释器在管理程序领域中的位置。

要找到这些项,我们需要知道管理程序中某些代码的位置。我们不能简单地读取管理程序代码。我们缺乏适当的权限。相反,我们通过BHB泄漏代码位置。如何?我们将要求管理程序代表云实例执行一些正常操作。在这些操作过程中,管理程序执行间接分支,其位置将存储在BHB中。然后我们“读取”BHB以识别这些代码位置。

一旦我们知道管理程序中的一些代码位置,通过一些数学和多次重复尝试,我们可以找到readerebpf_codeindirect_branch和eBPF解释器在管理程序领域中的位置(图4)。

图4: 完成此攻击描述步骤6后云计算系统的简化图。攻击者已收集进行攻击所需的所有信息,但关键部分仍在后面。

攻击执行

我们确保reader的任何部分都没有被缓存。

是时候施展魔法了!我们执行一系列间接分支,将新条目写入BHB。这些分支及其目标被设置为欺骗间接分支预测器,使其猜测indirect_branch指向eBPF解释器(图5)。

图5: 这是Spectre V2攻击的核心:特殊制作的间接分支可以欺骗分支历史缓冲区预测攻击者选择的推测目标用于间接分支。在这种情况下,管理程序中的间接分支被设置为推测指向eBPF解释器代码而不是其原始位置。

泄漏秘密

我们设置处理器状态,以便如果它开始执行eBPF解释器,那么解释器将运行ebpf_code,这将依次读取一个管理程序内存字节,并使用该字节访问reader的一部分。

我们要求管理程序执行一个保证触发indirect_branch的无害操作。现在发生一系列复杂的事件:

  • 处理器将猜测indirect_branch指向eBPF解释器。
  • 处理器将开始推测执行eBPF解释器。同时,倒计时开始,直到处理器知道它猜错了分支目标。
  • eBPF解释器将执行由ebpf_code提供的指令,这将:
    • 读取一个管理程序内存字节。
    • 使用该字节访问reader的一部分。
    • 导致该部分reader被缓存。
  • 处理器发现它执行了错误的分支,并取消执行迄今为止所有推测执行的指令。然而,reader的一部分现在在缓存中(图6)。

与Meltdown和Spectre V1一样,我们计时访问reader的每一部分,并识别哪一部分读取速度远快于其他部分。该部分的索引是我们从管理程序内存读取的字节的值。

我们可以重复此过程以读取更多字节,尽管设置较少,因为我们可以跳过攻击准备步骤。

图6: Spectre V2攻击中秘密如何泄漏的可视化。eBPF解释器推测执行攻击者指定的eBPF代码,该代码将读取一个秘密值并使用它访问reader。推测执行的效果可以通过缓存计时侧信道观察到。

再次强调,上述步骤大大简化,以展示一般概念和工作中Spectre V2攻击涉及的一些激动人心的技巧。每个步骤本身都非常复杂(即,一个人不能简单地“读取”BHB)。

影响是什么?

这对每个人来说都是非常坏的消息——无论您是云提供商、互联网公司,还是仅仅是网络公民。影响结合了Spectre(变种1)最糟糕的部分和Meltdown最糟糕的部分。与变种1不同,没有针对Web浏览器的概念验证,但不能排除可能性。

对云提供商来说,消息更糟。有一个概念验证利用打破了用于在云计算系统上分离租户的最强隔离机制。此外,不仅是Intel,多个CPU架构的各种供应商的处理器都容易受到变种2的攻击。

有多种缓解措施可用,每种都有一些性能成本。处理器供应商提供了更新,调整其处理器的工作方式以减轻影响。当不可能时,可以重新编译软件以避免使用间接分支指令。我们未能找到这些修复性能损失的可靠数字,但它们肯定不是零,并且必须与修复Meltdown的惩罚一起支付。

我该怎么办?

将您的操作系统和固件(即BIOS或UEFI)更新到最新版本。最新的操作系统和BIOS更新将通过处理器微码更新、控制间接分支预测器行为的变通方法或重新编译以避免间接分支来缓解变种2的最严重实例。

所有主要云提供商都已部署缓解措施。作为客户,您无需担心。

这是怎么发生的?

那么,一个基本的计算机设计缺陷如何在过去25年中未被注意到?答案有两部分:我们对计算的基本假设已经改变,并且关于这些安全影响的许多提示直到现在才被组合成一个工作的概念验证。

当推测执行在90年代首次出现在消费处理器中时,我们使用计算机的方式是不同的。大多数机器是单用户的,当时最流行的操作系统——Windows 9x和Mac OS Classic——缺乏内存保护。您不需要Spectre或Meltdown来读取(甚至写入!)另一个应用程序的内存——您可以直接这样做。在那个环境中,性能提升是真实的,而安全影响不是。

如今,多租户云计算,无论是使用虚拟机还是容器,驱动了网络的巨大一部分。Web浏览器下载并运行不受信任的代码(即JavaScript),这些代码应该与其他不受信任的代码(即您打开的其他标签页)沙盒隔离,这是常规发生的情况。在这个环境中,从一个隔离的内存隔间泄漏信息到另一个(例如,浏览器标签之间)是一个巨大的问题。

有许多提示表明推测执行可能导致特权信息泄漏。Google Project Zero博客文章引用了多个来源(包括我们自己的Sophia D’Antoine的一个),暗示了这个问题。多个独立研究人员识别并报告了Spectre和Meltdown漏洞,其他人也非常接近。然而,认为可能存在问题和编写概念验证显示问题是真实的存在很大差异。报告此问题的研究人员所做的工作非常出色。我希望这篇博客文章展示了这是多么困难。

结论

我们希望您在技术层面上更好地理解Meltdown和Spectre的工作原理、它们的影响以及可用的缓解措施。这篇博客文章是为没有计算机架构背景的人编写的,我们真诚地希望我们成功了。对于我们更技术性的读者,Meltdown和Spectre论文以及Project Zero博客文章是更详细的来源。

展望未来,对计算平台的微架构攻击将成为计算机安全的一个激动人心的领域。因为许多部署的平台容易受到Meltdown和Spectre的攻击,微架构攻击将在未来许多年继续相关且危险。

如果您喜欢这篇文章,请分享: Twitter LinkedIn GitHub Mastodon Hacker News

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计