Meltdown和Spectre分析以及CPU芯片漏洞攻击实战,教你如何破解macOS上的KASLR。html
做者:蒸米,白小龙 @ 阿里移动安全 来源:git
https://paper.seebug.org/497/github
0x00 影响缓存
早上忽然就被Meltdown和Spectre这两个芯片漏洞刷屏了,但基本上都是一些新闻报道,对漏洞的分析和利用的信息基本为0。做为安全研究者,不能只浮在表面,仍是要深刻了解一下漏洞才行,因而开始研究这方面的资料。结果发现其实这个硬件漏洞的影响很是广,不光是Intel, ARM和AMD也受影响,只是AMD的影响比较小罢了。所以基本上全部的操做系统(Windows,macOS,Linux,Android等)都有被攻击的风险。漏洞有两种攻击模式:一种被称为Meltdown,是在用户态攻击内核态,形成内核信息泄露。另外一种被称为Spectre,一个应用能够突破本身的沙盒限制,获取其余应用的信息。另外,由于是硬件漏洞,这个攻击对云的影响很是大,利用这个漏洞,一个guest能够获取host或同一台服务器上其余guest的信息,能够说是一个很是严重的漏洞,所以亚马逊和google都在紧急加班修复漏洞。好比google就公布了漏洞修复的进度在:https://support.google.com/faqs/answer/7622138。虽然是硬件漏洞,可是在系统或软件层面上经过牺牲性能的方法仍是能够进行修补的。安全
0x01 缘由服务器
那么咱们如今知道漏洞很严重了,那么漏洞造成的缘由是什么呢?关键点在于Speculative execution(推测执行)。推测性执行是一种优化技术,CPU会执行一些可能在未来会执行任务。当分支指令发出以后,传统处理器在未收到正确的反馈信息以前,是不会作任何工做的,而具备预测执行能力的新型处理器,能够估计即将执行的指令,采用预先计算的方法来加快整个处理过程。若是任务最终没有被执行,CPU还能够回滚到以前的状态,就当作什么都没发生过同样。可是这样真的安全吗?答案是,并不安全。攻击者经过寻找或构建一些指令就能够在CPU回滚的时间窗口里进行一系列的攻击。好比Google Blog中提到的边界检查绕过(CVE-2017-5753),分支目标注入(CVE-2017-5715), 恶意数据缓存加载(CVE-2017-5754)。ide
举个例子,若是CPU执行下面这段代码:性能
arr1->length没有被缓存的时候, CPU会从arr1->data[untrusted_offset_from_caller]处读取数据,若是untrusted_offset_from_caller的值超过arr1->length,就会形成越界读。固然,正常状况下这并不会出现什么问题,由于在执行到判断语句那一行的时候,CPU发现不对,后面的语句不该该被执行,因而会将状态回滚到越界读以前。fetch
可是接下来,问题就出现了。假设arr1->length,arr2->data[0x200]和arr2->data[0x300]都没有被缓存,CPU会继续推测执行下面的代码,在这里index2会根据value&1产生两个不一样的值0x200,0x300,而Value就是越界读到的值。接下来,代码会根据Value的值去读取arr2->data[0x200]或arr2->data[0x300]的值而且这个值会被加入到缓存里。接下来,咱们能够再次尝试去读取arr2->data[0x200]和arr2->data[0x300],读取时间短的那个值说明被缓存过了,所以就能够判断出value&1的值为0仍是1,从而作到内核信息泄露。优化
其实,在google的blog发布以前,就已经存在相似的攻击了,只是危害没有这么大而已,今天咱们就直接实战一个利用Intel CPU芯片漏洞来破解macOS KASLR的攻击。
0x02 芯片漏洞实战之破解KASLR
这种攻击比较简单,可是是后面高级攻击的基础,所以咱们先从这个攻击讲起。以前咱们讲到,为了让CPU效率更高,它们依靠推测性执行在任务到来以前就提早执行任务。一样,数据预取就利用这个思想推测性地先将数据加载到缓存中。Intel的CPU有五个软件预取指令:prefetcht0,prefetcht1,prefetcht2,prefetchnta和prefetchw。这些指令做用是提示CPU,告诉他一个特定的内存位置可能很快被访问。然而,Intel的手册中却提到,预取“未映射到物理页面的地址”会致使不肯定的性能损失。所以,咱们能够经过CPU预读指令执行的时间长短来判断这个地址有没有被映射到物理页面上。
咱们知道KASLR的原理是在内核的基址上增长一个slide,让攻击者没法猜想内核在内存中的位置。可是内核确定是被映射到物理页面上的,所以咱们可使用预取指令去遍历内核可能的起始地址,若是执行预取指令的时间忽然变短,就说明咱们猜中了内核的起始地址。咱们在网上成功找到了破解macOS 10.13 KASLR的POC,并作了一点简单的修改:https://pastebin.com/GSfJY72J
其中关键代码以下:
这是一段汇编,参数会传入想要预取的地址,而后利用rdtscp和rdtscp来统计指令执行的时间,并返回。因而咱们从内核可能的起始地址开始,不断地执行这段汇编代码,直到咱们找到内核的起始地址为止。
能够看到在0x15c00000这一行,指令执行的时间明显缩短了。所以,咱们能够猜出Kernel Side为0x15c00000。
0x03 修复
根据某内部漏洞修复人员在twitter上的回复,苹果已经在macOS 10.13.2上对此类芯片漏洞进行了修复,采用了牺牲性能的针对用户态使用两次映射的方式来解决该问题。并号称10.13.3上有更好的解决方案。另外iOS的A*系列芯片暂时还不受这类漏洞的影响。
0x04 总结
本篇文章只是给芯片的一系列漏洞开了个头,咱们随后还会有更多关于芯片漏洞的分析和利用实战,欢迎继续关注本系列的文章,谢谢。
参考文献:
1. https://googleprojectzero.blogspot.hk/2018/01/reading-privileged-memory-with-side.html
2. https://siguza.github.io/IOHIDeous/
3. Prefetch Side-Channel Attacks: Bypassing SMAP and Kernel ASLR, CCS 2016.