来源:首席安全官Plus(ID:csoplus)
首席安全官Plus是由一群科研院所的网络空间安全研究人员发起成立的民间网络空间安全知识平台,努力打造“有特色、高水平、国际化”的网络安全思想高地。围绕“大数据、云计算和人工智能”等高技术领域的网络安全前沿技术、产业趋势和资本市场,汇聚一流资源,产出一流安全洞察。如投稿,请发送到:[email protected]。
欢迎扫码关注我们的公众号,谢谢!
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
现代处理器通过一些微体系结构的部件来预测未来的程序行为,从而达到提高处理器性能的目的。这就需要相关微体系结构的部件能够记录过去程序行为的状态,并假设将来的行为与过去的行为相似或相关。
然而,当多个程序在同一硬件上执行时,无论是并发执行还是分时执行,由一个程序的行为引起的微体系结构状态变化可能会影响到其他程序,进而可能会引起机密信息从一个程序泄漏到另一个程序中。
01 分支预测逻辑的程序示例
例如,考虑下面的两行代码:2个数组array1和array2,2个临时变量x和y,1个常量array1_size,表示数组array1的长度。
if (x < array1_size)
y = array2[array1[x] * 4096];
图1:条件分支执行代码示例
该代码片段的第一行用x < array1_size进行边界安全检查,防止读取array1边界外的机密信息,同时触发一个数据越界异常。
需要注意的是,读取array1边界外的机密数据可通过提供机密数据内存地址与arary1基地址的相对位置进行计算,而相对位置又可以通过挨个尝试取得。如下,x表示机密数据内存地址与arary1基地址的相对位置,即得:
机密数据内存地址 = array1基地址 + x
02 分支预测逻辑的运行原理
程序在处理器上执行时可能会由于处理器因边界检查期间或之前的缓存丢失、边界检查依赖的执行单元拥塞以及复杂算术依赖或嵌套推测执行等原因,导致边界检查延迟执行。这使得在获取到边界检查结果前,条件分支后的代码已经在微体系结构层面预先推测地执行了最有可能执行的分支条件后的执行代码。上图介绍了在上述条件分支执行时的四种分支预测场景:
1) 实际程序的边界检查条件为true,分支预测也为true。在这种情况下,程序有权限进行分支后的代码执行,分支预测部件也推测该程序有后续执行的权限,因此边界检查完成后,发现分支预测与实际一致,直接提交边界检查期间预测执行的结果,大大地提高了处理器的执行性能。
2) 实际程序的边界检查条件为true,分支预测为false。在这种情况下,程序有权限进行分支后的代码执行,但是分支预测部件认为该程序不具有后续执行的权限,因此边界检查完成后,发现分支预测与实际不一致,该程序仍有权限进行后续执行,继续执行后续代码就可以了,只是不会提前执行有性能的提高而已,不存在机密信息泄露风险。
3)实际程序的边界检查条件为false,分支预测为true。在这种情况下,程序并没有权限进行分支后的代码执行,但是分支预测部件认为该程序具有后续执行的权限,会推测地预先执行分支后的代码,产生了越权行为,因此存在机密数据泄露的风险。
4) 实际程序的边界检查条件为false,分支预测为false。在这种情况下,程序并没有权限进行分支后的代码执行,分支预测部件也认为该程序不具有权限进行后续执行,因此该分支完全不执行,不存在机密信息泄露风险。
因此,在上述场景三的情况下现代处理器内核分支预测逻辑是存在漏洞的。
03 分支预测逻辑的漏洞利用
由分支预测逻辑的运行原理可知,攻击者要利用分支预测逻辑的漏洞就需要构造场景三,并确保以下三个条件:
1) 在x不越界的情况下训练分支预测器,让分支预测器误认为if条件一直为true。
2) 选择一个越界的值x使得array1[x]对应为受害者机密信息k的内存地址;
3) 确保array1_size和array2不被缓存,而k已经被缓存
在确保上述三个条件之后,处理器执行图1的代码片段时,开始比较x 是否小于array1_size,在读取array1_size值的时候发现Cache没有命中,因此处理器要等待读取内存DRAM中的array1_size值。
同时,分支预测器推测地认为if条件为true,因此预测执行逻辑将x与array1的基地址相加进而得到受害者机密数据的内存地址,然后去内存子系统读取机密数据,发现Cache命中,因此会快速的读取k(即array1[x])的值。
然后,预测执行逻辑会使用k来计算arrary2[k*4096]的地址,并读取该地址内存信息,发现Cache未命中,然后去内存DRAM中读取arrary2[k*4096]的值,而在这个读取过程中,边界条件检查结果已经得到确定,处理器意识到推测地执行是错误的做法,并开始回滚寄存器状态。然而,array2的预测读取是基于k的特定地址进行的,会影响到array2在Cache中的状态。
为了完成攻击,攻击者需要借助基于时间访问驱动的Cache侧信道攻击来获取机密数据k。主要有两种方式:
1) 根据arrary2[k*4096]来判断array2的哪一个内存位置曾经被写入Cache(即Cache命中)即可,在得到内存位置后可直接推算k的值;(如Flush+Reload 、 Prime+Probe)
2) 根array1[x’] 是否Cache命中(命中时array1[x’]等于k),通过选择x’进行度量。(如Evict+Time)
转载请注明来源:首席安全官Plus ( 微信号: csoplus),谢谢!