Security 幽灵的例子
在spectre中,有一个利用越界阵列访问的示例(第1.2节)。代码是Security 幽灵的例子,security,spectre,Security,Spectre,在spectre中,有一个利用越界阵列访问的示例(第1.2节)。代码是 if (x < array1_size) y = array2[ array1[x] * 256 ]; if(x
if (x < array1_size)
y = array2[ array1[x] * 256 ];
if(x
该过程是使用一些有效的x
值来训练正确的路径。然后给出一个无效值x
,同时假设arra1\u size
未缓存。由于分支预测器认为该条件为真,它将推测性地获取array2的偏移量
现在,问题来了。在推测性执行中,它必须获取array1[x]
,其中x是恶意的,它是越界的。所以,array1[x]
实际上是无效的!那攻击是什么?!没有提取有效数据
有人能给我解释一下吗?这里有什么误解?我的理解(简化)(可能是错误的):
当x高于边界时,处理器将加载更高的数据
在别的地方。(有点像缓冲区溢出)
例如,当数据按如下方式保存时:
1Spectre(与Metldown不同)的工作原理取决于CPU如何处理分支预测。来自你提到的同一篇论文
[2.3]推测性执行要求处理器猜测分支指令的可能结果。更好的预测通过增加可成功提交的推测执行操作的数量来提高性能。(…)
要预测是否执行条件分支, 处理器保存最近分支结果的记录 然后 [4] 代码片段以
x
上的边界检查开始,这对安全性至关重要。特别是,此检查可防止处理器读取array1
之外的敏感内存。否则,越界输入x
可能触发异常,或通过提供x=(要读取的秘密字节地址)导致处理器访问敏感内存−(阵列1的基址)
但论文继续解释了为什么这可能会起作用,而不会引发异常:
不幸的是,在推测执行期间,边界检查的条件分支可能遵循错误的路径。例如,假设对手导致代码运行时:
•恶意选择x
的值(在边界之外),使得array1[x]
解析为受害者内存中某个地方的秘密字节k
•array1
大小和array2
不存在于处理器的缓存中,但k被缓存;及
•以前的操作收到有效的x
值,导致分支预测器假设if可能为真
最后,在计算出x
值过高后,CPU将有效绕过if
主体,并且不会使检索到的y
值失效。但是,缓存状态已更改,这就是攻击发生的地方:
处理器意识到其推测执行是错误的,并倒带其寄存器状态。但是,在实际处理器上,从array2
进行推测性读取会以特定于地址的方式影响缓存状态,其中地址取决于k
对array1[x]
的未经授权的访问是在推测代码执行期间进行的,因此不会引发异常,因为CPU“知道”如果前面分支的条件恰好为false,则该推测执行的结果将不会失效
(与Meldown不同,Meldown在执行的用户代码访问未经授权的区域时触发异常-Meldown利用异常失效所需时间与访问之后的几个预执行(且不会失效)的无序指令之间的竞争条件)
所以,数组1[x]实际上是无效的!那攻击是什么?!没有提取有效数据
这是攻击的重点。索引(即x
)可能太大了,因此我们可以访问本不应该访问的数据
例如,如果我们的代码在JavaScript沙盒或Java虚拟机中,我们将能够访问沙盒/虚拟机之外的数据
更重要的是,推测执行可能访问内核页面,即我们没有权限访问的页面。这就是崩溃
以下是我基于幽灵的熔毁概念证明,仅99行,您可能会发现更容易理解:
我认为你在这个话题上的回答与我的问题没有直接关系。我想知道的是越界的例外。假设一个数组有10个项目,那么范围是0..9。现在cpu推测性地从索引8中获取一些项。那是9,10,11,12
array1[10]
无效,它应该在将发生的附加之前引发异常。这不是吗?我在下面回答。(对投机性攻击更具解释性)。推测执行的代码不会给出异常(否则类似于C中的代码,if(arr[x]!=NULL)*arr[x]=3;
,其中*arr[x]当x
为NULL
时,=3
可以推测运行,将触发用户不应获得的异常,因为分支条件最终将计算为false,推测运行代码未失效。如果没有cflush命令,如何实现spectre?例如,是否可以使用exect+Reload?在github上,我似乎没有看到任何人成功地将刷新重新加载替换为逐出+重新加载?如果我使用逐出+重新加载,是否每次都必须清除整个缓存中的所有缓存线?