为什么这种缓存攻击有效?

信息安全 javascript 记忆 定时攻击 侧信道
2021-08-15 00:14:10

我最近正在阅读以下有关在 Javascript 中进行缓存攻击的论文:

https://arxiv.org/pdf/1502.07373v2.pdf

但我对它如何工作感到困惑。在论文中,一个 8 MB 的缓冲区足以让找到驱逐集的成功率很高(对于 12 路缓存)。我不确定这怎么可能。

我为自己的计算机计算了数字,但它似乎不起作用(3MB 缓存,12 路):

  • 驱逐缓冲区可以是 4 MB 而不是 8 MB
  • 这是缓冲区索引将存储的内容:
    • 位 0 - 6:高速缓存行中的字节
    • 位 6 - 12:设置索引的前 6 位
    • 12 之后的位:没有用,因为它可以映射到任何物理地址
  • 驱逐缓冲区中有 1024 个页面
  • 在这 1024 个页面中,需要有 12 个映射到与受害地址共享相同位 12-18 值的物理页面。我不擅长概率,但这似乎很不可靠

为什么它有效?

我在自己的电脑上试过了,它似乎能够在 70% 的时间里驱逐受害者地址(尽管即使我根本不运行任何驱逐程序,受害者地址似乎仍然得到一个大约 20% 的失误率)。

1个回答

假设操作系统完全随机分配页面,我的最佳计算表明任何给定的受害者地址在 4MB 缓冲区中至少有 12 个匹配页面的可能性约为 11%。这不太可能,当然也不符合您看到的 70% 的成功率。

但是,操作系统有充分的理由避免随机映射页面,而是尽量映射连续页面。造成这种情况的一个原因是操作系统有时需要分配大的连续缓冲区(例如,以支持大页面或大 DMA 缓冲区),而物理页面的随机分配会使得很难找到足够大的区域。这称为内存碎片。

但在本次讨论的上下文中,连续分配的一个更有趣的好处是(具有讽刺意味的是)3 级缓存性能。如果您正在运行使用大内存缓冲区的算法,则获得最佳性能的方法是分配连续的物理内存,以便各个页面不会从缓存中相互驱逐。如果操作系统以这种方式成功地最大化性能,那么它也将成功地最大化攻击的有效性:您的 4MB 缓冲区将覆盖整个缓存,并且您将有 100% 的机会驱逐受害者页面。因此,您观察到的 70% 成功率不是对机会的衡量,而是对操作系统在分配页面以获得良好缓存性能方面的有效性的粗略衡量。


如果您想查看一个在实践中以这种方式工作的操作系统示例,请阅读Linux 的 buddy allocator它首先将内存分成一组大的空闲块。然后,如果它想分配一个页面,它会占用其中一个大块并将其分成两半。然后它取其中一个并再次将其分成两半,并继续直到它得到一对 1 页大小的块——此时它也有一个 2 页大小的块,一个 4 大小的块,一个8 大小等。前两个分配将是这两个 1 页块,它们彼此相邻,因为它们是将 2 页块分成两半的结果。第三次分配会将另一个 2 页块分成两半,出于同样的原因,它又会紧挨着另外两个。

因此,每当它需要一个新页面时,分配器就会获取它可以找到的最小块并将其分解,直到它得到一个页面。最后,当一个页面被释放时,分配器检查它旁边是否有一个空闲页面,因此它可以将这两个页面重新组合成一个更大的块。最终效果是尽可能保持分配大致连续。