阿尔法实验室研究人员通过结合POC对整个漏洞原理流程还有漏洞细节做了进一步更详细的技术分析。
在本文中将详细分析POC中每个环节的关键点和漏洞的所有细节,包括漏洞形成的原因、漏洞攻击思路和方法、漏洞攻击流程,还有如何在浏览器中利用此漏洞,造成什么样的影响。
二 POC流程介绍先介绍下poc执行流程
(图 2.1)
图 2.1是一段利用分支执行漏洞的代码,有这段代码才能在分支预算并推测执行,我们要获取的是放入内存中的secret “Topsec test this vul!!“这段字符。 Topsec中的T的地址用addr(T)表示
(图2.2)
图2.2中的编号1(malicious_x 会被传入到victim_function中,因为malicious_x = addr(T)-addr(array1),所以array1[malicious_x] =T ,这个原理跟数组寻址有关。我们只要知道array1[x]就是我们的secret中的“T”,而且正常情况下,如果x比array1_size值大,array1[x]是没办法读取的,但是如果做一个训练让x值前几次都比array1_size小,然后放入malicious_x,如此循环几次触发了分支预算,cpu预算出x比array1_size小的概率很大,当malicious_x再次放入时候(这个malicious_x实际上是比array1_size大的),cpu就推测malicious_x比array1_size小,导致推测执行了读取了(array1[x]的值*512)作为下标放入了array2中,但是系统是有保护的,因为malicious_x已经超出了数组array1的大小,只是CPU缓存区在计算读取的数据放到了CPU的缓存中,因为异常所以并没有真正的执行写入到内存中。这就是漏洞产生的原因,下面会有数据来更详细的解释。
图2.2编号2中的len=24就是我们“Topsec test this vul!!“的长度,图2.2编号3中会打印secret第一个偏移地址A0 Reading at malicious_x = 00000000000000A0…
图2.2编号4中readMemoryByte 函数中可以看到有三个参数,第一个是secret的地址,vulue是secrect的值,score中是评分值。
以下是介绍攻击者模拟一个训练集让CPU执行分支预测并推测执行。
(图2.3)
图2.3编号1和3是清空数组的在cpu的缓存,图2.3编号2是我们训练集的值,开始为7然后递减循环不超过16这个array1_size的大小,每个训练5组,每组在第六个放入secret的地址,图2.3编号4,5,6是让x的值从7开始递减循环并训练5组的公式,图2.3编号7是调用有漏洞的函数。如何触发漏洞后面会讲。
三 漏洞原理详细介绍该漏洞触发原因是分支预测,什么是分支,判断就是分支。
if (x < array1_size)什么是预测,有一些数据提供判断的依据去推断就是预测。
比如有一个数据集x,这个x可以是攻击者伪造的,攻击者设计了好多比array1_size小的数据集去让系统执行分支预测这个功能,让分支预测的结果一直是x比array1_size小,这里array1_size的大小是16,unsigned int array1_size = 16;
下面的这个图是我打印的x的值,
x先从7开始放入victim_function(x)中,每次循环有五组训练集,7开始为第一个训练集,在这个训练集中,每次放入5个7,第六个放入malicious_x也就是A0, 前五次放入victim_function函数中的是5个7< array1_size=16,这是在训练CPU的分支预测功能,让cpu分支预测以为x比array1_size的值小,再第六个突然放入了一个比array1_size大的值也就是malicious_x =0xA0,照成了越界访问抛出了异常,但是这时候推测执行已经把”T*512”作为array2的数组下标并取值放到了cup缓存中,但是并没有真正的去执行,如果你在判断里打印x的值,你会发现不会有malicious_X,只有0~15这几个值。因为系统还是有保护的,发现异常后cpu不会把计算后的值写入内存,不然这个漏洞就不光是可以读数据了,如果没有这层保护,那这个漏洞影响就更大了。
接下来的训练集是递减 (7,6,5,5,3,2,1,15,14,13,12,11…) ,每组五次一直循环,直到找到我们要的结果。之所以训练这么多组是因为训练的越多,让分支预测按攻击者的逻辑判断去执行的成功率越大,简单说就是一组不行两组两组不行三组直到计算出来为止。
下面我们介绍readMemoryByte 函数中的旁路攻击,
因为之前的array2的下标array1[malicious_x]*512的值已经在cpu的缓存中,然后通过遍历数组array2中哪个地址的访问速度快就是可能是我们的secret。