问题中的代码是指 Spectre Variant 1,也称为bounds check bypass。
这里有什么误解?
与其从受害者进程和攻击者进程的角度考虑变体 1,不如将其视为沙盒攻击者代码,其目标是读取其沙盒之外的内存。
换句话说,攻击者控制了一些在软件沙箱中运行的代码,而这个软件沙箱通常会强制每个代码域只访问自己的数据。但是,Spectre 允许攻击者的代码绕过此类沙箱的强制执行。
例如,攻击者为恶意网站提供 Javascript 代码,该恶意网站将在执行时被 Javascript 解释器沙箱化。Javascript 解释器将检查诸如y = array2[ array1[x] * 256 ]
只能执行 if的代码x < array1_size
。这称为边界检查,用于确保不允许网站从运行它的浏览器进程的地址空间中读取。在执行时,攻击者(谁控制x
)可以通过让他们自己的代码训练分支预测器来执行条件分支错误预测以获取分支if (x < array1_size)
。最后,攻击者将设置x
到一个期望的越界值,由于 Spectre,这将允许他们绕过沙箱的边界检查并从浏览器进程的地址空间中读取内存。总之,这里的攻击者控制了(沙盒)网站的代码,Spectre 允许他们读取打开网站的浏览器的内存(这通常会被沙盒阻止)。
第二个例子使用 eBPF,攻击者从 Linux 内核注入并执行一些代码。eBPF 接口允许非特权用户这样做。此代码通常会在内核虚拟机/沙箱中执行,该虚拟机/沙箱执行边界检查以防止加载的代码读取任意内存。但是,Spectre 允许攻击者在 BPF 沙箱之外违反此沙箱并泄漏任意内存。总之,这里的攻击者是主机的非特权用户,Spectre 允许他们读取主机上的任意内存!
但在现实世界中,攻击者和受害者是分开的(他们是不同的过程)
在这种情况下不是。如上所述,在 Spectre 变体 1 中,“受害者的代码”将“攻击者的代码”封装在同一进程中。攻击者的代码通常会被受害者使用软件沙箱隔离,但 Spectre 允许绕过它并读取受害者地址空间中的任何内存。