您只需要推测即可渗透
Meltdown和Spectre如何破坏设备安全性
在CriticalBlue中 ,我们一直在讨论新发现的Meltdown和Spectre缺陷及其对设备安全性的影响。 我们的首席技术官Richard Taylor写了一篇博客文章 ,概述了这些漏洞。 这是一个清晰的解释,并且比大多数解释要深入一些,因此我在下面列出了他的想法,以帮助您理解。
上周安全新闻流之后,还有很多要讨论的问题。 它由Meltdown和Spectre CPU错误公告所主导-2018年肯定是一个有趣的开始。 在这个由两部分组成的博客的第一部分中,我将从较高的角度来看这些错误。 在第二部分中,我将重点介绍对移动安全(特别是对Android)的影响。
尽管针对这些错误的补丁已经投入使用了一段时间,但公告还是匆忙发布,并且有时会显示出来。 但是,Register和Ars Technica等提供了一些出色的报道,在此不再赘述。
缓存侧通道攻击并不新鲜,但是直到现在,其中许多攻击还是人为设计的。 为了使攻击正常进行,您需要窃听的受害应用程序必须发出一个强烈的信号,而这对于攻击者而言是最大的挑战。 在这种情况下,强信号意味着高速缓存行访问模式本身会泄露一些秘密数据。 换句话说,数据必须以特别方便的方式影响存储器访问模式。 您需要尝试窃取一些关键数据来计算地址,这些地址可以方便地跨越许多高速缓存行,从而为您提供一些良好的高速缓存侧通道信息,以便以后进行监视。 此外,您需要该缓存布局保持完整的时间,以使您的窃听代码可以观察到它。 通常,高速缓存布局信息会因受到攻击的代码执行的其他操作而迅速降级。 这些要求在现实中并不经常发生,因此,尽管有一些不错的旁通道通信演示,但在要攻击的代码中找到好的信号发生器的机会实际上却很小。
崩溃和幽灵从根本上改变了游戏。 您需要制作自己的信号生成代码,然后您可以窃听自己的声音。 很方便。 这更加通用并且功能强大。 这里的关键见解是使用推测执行为您执行此操作。 为了保持良好的性能,CPU会大量执行推测性执行。 特别是,它们预测分支可能采用的方式,并且事实证明,它们有效地预测了,当然,肯定可以访问您刚刚读取的内存位置。
首先,让我们处理Meltdown,它实际上只会影响Intel CPU。 正式而言,这是Rogue数据缓存负载( CVE-2017–5754 ),这是对CPU乱序推测性质的相当巧妙的滥用。 您要做的第一件事是从不具有读取权限的内存位置加载。 当您执行此操作时,您的代码将获得异常并且将停止,并且当然不会直接告诉您该内存位置中保存了什么。 但是,事实证明,它不会立即执行此操作,因为它将异常作为负载本身的单独子操作处理。 因此,如果您巧妙地构建代码,则实际上可以进行数据加载并将其转换为地址,然后从该位置加载。 现在,当异常最终赶上您时,您从原始加载中获得的所有寄存器状态都会回滚。 好像从未发生过一样被冲走了。 但是,您从该数据相关地址读取的事实仍然保留在缓存状态中。 它没有被冲走。 这种痕迹仍然存在,并且通过仔细测量代码中另一个线程的缓存状态,可以推断出数据是什么。 这是一个坏消息。 现在,您可以有效地读取想要的任何内存,尽管从统计角度和间接角度来说都可以。 真正可怕的消息是,默认情况下,Linux和Windows使机器的所有内存都可以在进程地址空间中访问。 因此,攻击代码可能会访问所有秘密数据,密码和其他有用的块。 如果您可以在目标计算机上运行代码,那么理论上您可以阅读任何内容。 CPU安全隔离方面的破坏性很大的监督。 真正引人注目的是,迄今为止还没有发现。 投机执行已经存在了很多年。 正是这些见解之一,导致您一旦意识到其中的含义,便会集体发出“当然,为什么以前没有人想到它”的感叹。 修复Meltdown的修补程序已经投入了一段时间,并准备很快推出。 基本上,解决方法是确保为某个进程映射MMU的唯一页面是应该能够以任何方式读取的页面,否则就不会很有趣。 这被称为Linux的内核页表隔离( KPTI ),并且即将推出的Windows也有类似的修复程序。 但是,这会对性能产生影响。 有充分的理由使其余内核页面可以快速访问。 即使系统性能下降,我们也不会受到Meltdown的伤害。 因此,尽管最初的大部分歇斯底里都围绕着Meltdown的影响,尤其是在AWS等多租户云环境中,但补丁周期似乎很快就会赶上,然后Meltdown可能会从头条新闻中消失。 尽管主要的Meltdown错误不会影响ARM CPU,但它们定义了一个特殊的变体3a ,某些系统寄存器的内容可以泄漏给普通进程,但总的来说,这似乎不如Intel系列严重。 基于ARM硬件的PoC已经在运行 。
我怀疑幽灵会一直存在。 正如发现此漏洞的研究人员所指出的那样,它肯定会困扰我们很多年。 其影响更深,更难缓解。 与Meltdown不同,Spectre同样会影响ARM和AMD设备。 这意味着手机和平板电脑也都在框架中,以防与Spectre相关的数据泄漏。
Spectre有两种变体。 第一个被称为边界检查绕过( CVE-2017–5753 )。 基本上,这需要相当特殊的代码序列,包括条件值的范围检查。 它使用分支预测来执行不应执行的代码块。 这个想法是训练分支预测器执行一些条件代码,然后传递一个它不应该执行的值。 但是,必须仔细构造条件检查,以便不能立即对其进行评估。 因此,CPU将像上次一样继续执行条件代码,而不是浪费时间。 有什么害处吧? 没有什么比这更好的了。 条件代码构造为从攻击者控制的任意内存位置加载数据,然后将该数据用作地址以再次从内存加载。 这里与Meltdown有明显的相似之处。 即使在处理器紧追其后,并且意识到它永远不应该执行该代码路径之后,第二次加载仍会对缓存布局产生影响。 因此,基本上,您可以读取该进程可以读取的任何内存。 您还需要一个相对人为设计的代码序列来执行该代码序列,因为该序列不太可能自然发生,因此您确实需要能够自己生成该代码。 该错误使您可以有效地从进程可以从中加载的内存中加载。 您可能会问什么大问题。 嗯,最重要的是在流程上下文中运行的JIT和用户生成的代码。 内存绑定检查通常将确保此类代码不能仅读取任意内存,而只能读取其小沙箱中允许的部分。 此Spectre变体允许从沙箱中逃脱。 本公开显示了如何构造Javascript,然后将其JIT以生成确切的序列来利用此错误。 现在,在网页中运行的Javascript可能会访问所有浏览器进程内存。 这可能包括各种密码,凭据,Cookie和其他有用的机密花絮,那些运行广告的流氓Java脚本想要窃取您的数据都不应使用这些花絮。 许多浏览器在单独的进程中运行每个选项卡的事实似乎并不像我曾经认为的那种极端的锡纸帽子般的举动。 突然看来,这是有先见之明的。 我昨天第一次发现的另一件事是,即使Linux内核也具有JIT! 显然有一种叫做eBPF的东西可以用来泄漏任意内核数据。 毋庸置疑,针对所有这些问题的修复程序正在酝酿之中,但是修复程序更加复杂,需要使用特殊的防护指令生成不同的代码序列,以确保不良猜测不会以这种方式泄漏机密数据。 所有这一切的更广泛,更长期的含义是,除非您真的考虑过,否则您将无法信任允许在流程上下文中运行的用户代码。 即使将代码沙箱化,从而限制了它可以访问的内容,也不一定足够。 突然,我们必须意识到程序生活在一个奇怪的量子世界中,并且实际上可以采用它们本不应该使用的代码路径。 投机执行的抽象面纱已经被打破。
现在我们来介绍Spectre的第二种变体,分支目标注入( CVE-2017–5715 )。 这似乎是所有人中最奇怪的。 同样,这与分支预测有关,但是这次与间接分支有关。 间接分支发生得相当频繁,尤其是在允许多态方法覆盖的面向对象语言中。 因此,加快它们的速度非常重要,否则它们将变得很慢。 这是因为,CPU直到知道下一条指令才开始填充其流水线,而现代CPU的流水线要长得多。 事实证明,特定的间接分支上次到达的位置可以很好地预测下一次分支的位置。 同样,在没有更好的事情要做的情况下,典型的CPU会精确地执行该任务,并推测性地执行最后一个目标。 为了支持这一点,CPU中有一个称为分支目标缓冲区(BTB)的表,该表记录了从指令地址到该指令如果是间接分支将可能到达的位置的映射。 因此,当确定要进行下一次预测时,此信息将更新。 当然,该表不能无限大,并且条目之间存在一些冲突,但是将保留最常执行的指令。 它的作用就像最近间接分支的高速缓存一样,在某些体系结构中称为分支目标地址高速缓存(BTAC)。 如果您的代码停止执行,然后传递给内核,然后传递给在同一内核上运行的某些其他进程,则将保留BTB内容。 保留条目是有道理的,因为到轮到您的代码再次执行时,一些有效的条目可能仍然存在。 丢弃可能有用的信息以加快执行速度是没有意义的,这有什么害处? 如果目标地址是错误的,那么CPU仍然没有更好的工作,并且可以回滚错误的执行,就像从未发生过一样,然后可以将正确的目标分支到该地址。 好吧,我敢肯定,你可以看到它的去向。 众所周知,投机执行并非没有副作用,而且可以被利用。
Spectre分支目标注入的真正巧妙技巧是,攻击者可以选择推测执行的代码。 如果攻击者知道特定间接分支的地址,则他们可以训练BTB指向其想要的位置。 那需要的是已经在攻击过程中的代码,但是我们假设攻击者知道该代码的含义和位置。 该代码不需要执行干净,它只需要执行足够长的时间,就可以将有用的内容泄漏到缓存状态中,以便以后进行检查。 该代码是推测性的,无论如何它都是错误的预测,因此将回滚。 因此,基本上,如果攻击者想在间接分支调用站点上了解特定寄存器的值,则他们需要找到一些在地址计算和内存负载中使用该寄存器的代码,这将在高速缓存状态下留下足够明显的痕迹。 ROP小工具的功能非常强大。 这些是现有代码的简短序列,如果攻击者可以在允许他们控制目标地址但不能注入新代码的进程中导致缓冲区溢出,则攻击者可以凑在一起做一些有用的事情。 缓冲区溢出和ROP小工具链是应用程序安全性的祸害。 在Spectre案例中,我们拥有的是投机小工具。 我们可以在现有代码中选择正确的现有代码序列,这将为我们提供所需的泄漏签名。 与ROP小工具不同,尽管我们不需要现有的漏洞(例如缓冲区溢出)来利用它们。 我们只需要更早运行,并在BTB中设置陷阱即可迫使另一个进程的代码错误地推测并在缓存中保留一些有用的状态,以便我们稍后进行检查。 当然,在实践中,这很难设置,而且似乎更容易泄漏小块信息(例如单个字节或单词)而不是数据块,因为我们有毒的BTB培训很快就被撤消了,并且我们通过这些设备传输数据的能力有限。缓存状态。 在我看来,这种攻击最明显的用途是软件**记录。 可能每个存在于间接分支站点的寄存器都易于泄漏。 我们只需要找到一个例如保留系统上最后一次按键值的按钮即可。 当然,这可能是密码或机密消息的一部分。 不好。
请注意,为了利用此Spectre变体,有必要知道您要攻击的进程的确切代码布局。 您需要知道这一点,以便可以为要颠覆的间接分支正确设置BTB陷阱。 由于地址空间布局随机化( ASLR )如今已被广泛用作防御ROP小工具攻击的工具,因此这不一定很简单。 可以尝试多种方法来推断代码地址,但这确实在使这种攻击真正起作用所需的已经拜占庭式因果链中增加了另一层复杂性。
也正在针对此缺陷进行修复。 特别地,该方法依赖于上下文切换边界之外现有的BTB培训。 英特尔即将发布微代码更新 ,该更新将禁止跨边界保留条目,从而有效地使此漏洞无法利用。 ARM具有可用的类似补丁,可以跨上下文切换边界禁用或清除BTB。 在此阶段,尚不清楚这将对性能产生什么影响。 肯定会有一些。 传统上,出于良好性能的考虑,保留了BTB内容。 编译器补丁也以新的“ retpoline ”功能的形式出现。 这样就可以重新编译应用程序,使其不再受感染,或者确实可以使用此功能重新编译内核。 对于在未打补丁的环境中运行应用程序的情况,尤其如此。 Retpolines看起来很丑,但是可以解决此问题。 它们基本上使编译器用更复杂,更慢的序列替换间接分支和调用,从而滥用return指令执行相同的操作。 这要慢得多,但不受Spectre的影响,因为收益不使用BTB进行预测。 目前尚不清楚何时以及是否会针对其他编译和JITted语言(例如Java,C#,Python或Go)提供类似的Retpoline修复程序。
在第二部分中,我将讨论这一切对移动安全的意义。 这些错误绝对不仅限于英特尔设备。
谢谢阅读! 有关移动API安全性的更多信息,请访问www.approov.io 。
如果您推荐此帖子(单击????按钮),以便其他人可以找到它,我将非常感谢。
From: https://hackernoon.com/you-just-need-to-speculate-to-exfiltrate-a093a31aa904