Skip to content

Commit

Permalink
Add Meltdown
Browse files Browse the repository at this point in the history
  • Loading branch information
jiegec committed Jan 31, 2025
1 parent 5742506 commit 491ff64
Showing 1 changed file with 52 additions and 2 deletions.
54 changes: 52 additions & 2 deletions docs/hardware/cpu_vulnerabilities.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,57 @@
# CPU 漏洞和缓解措施

TODO:
## Meltdown

- [论文 Meltdown: Reading Kernel Memory from User Space](https://meltdownattack.com/meltdown.pdf)
- 允许用户态程序读取完整的内核态地址空间
- 原理:
- 硬件为了性能,在验证 load 指令的权限是否正确之前,提前把 load 指令的结果传递给了后续的指令,后续发现 load 指令的的权限错误后,再进行回滚
- 在用户态的时候,页表中内核态的地址也被映射了,只不过设置了权限位,禁止用户态访问
- 在用户态访问内核态地址会触发异常,但如果 load 指令的结果通过某种方式带来了副作用,就可以知道 load 的结果是多少
- 为了利用副作用来得到 load 指令的结果,首先把一个数组从缓存中清空,再把 load 指令的结果移位后作为下标去访问数组,那么副作用就是把对应位置的缓存行加载到缓存当中
- 最后再测量缓存行的访问时间,从而知道之前哪个缓存行通过副作用被加载到缓存当中,从而得到 load 指令的结果,而这本来是只有在内核态才能访问的数据
- 代码:
```asm
; rcx = kernel address, rbx = probe array
mov al, byte [rcx]
shl rax, 0xc
mov rbx, qword [rbx + rax]
```
- 从内核地址 rcx 读取一个字节,左移 0xc,也就是乘以 4096,再去访问 rbx 指向的数组。那么每个可能的 al 放在不同的页上,避免预取器干扰后续的测量
- 缓解措施:Kernel Page Table Isolation/KPTI/PTI/KAISER([论文 KASLR is Dead: Long Live KASLR](https://gruss.cc/files/kaiser.pdf)),在用户态的页表里,不要映射整个内核态空间,那么在用户态尝试读取内核态地址的时候,由于地址不在 TLB 当中,也就无法读取内存,不会泄漏数据
- PoC:[paboldin/meltdown-exploit](https://github.com/paboldin/meltdown-exploit)
- 这个 PoC 先用 root 权限读取 `/proc/kallsyms`,找到内核符号 `linux_proc_banner` 的地址,这主要是为了展示,方便拿到内核态地址,实际攻击者是没有 root 权限的
- 访问 `/proc/version`,使得 `linux_proc_banner` 符号在缓存中
- 在用户态用 Meltdown 读取内核态的 `linux_proc_banner` 的结果
- 在 Intel Xeon E5-2603 v4 上关闭 KPTI 后成功复现,成功读出来 `%s version %s (d`:
```
cached = 30, uncached = 316, threshold 97
read ffffffffa2400260 = 25 % (score=999/1000)
read ffffffffa2400261 = 73 s (score=1000/1000)
read ffffffffa2400262 = 20 (score=1000/1000)
read ffffffffa2400263 = 76 v (score=1000/1000)
read ffffffffa2400264 = 65 e (score=1000/1000)
read ffffffffa2400265 = 72 r (score=1000/1000)
read ffffffffa2400266 = 73 s (score=1000/1000)
read ffffffffa2400267 = 69 i (score=1000/1000)
read ffffffffa2400268 = 6f o (score=1000/1000)
read ffffffffa2400269 = 6e n (score=1000/1000)
read ffffffffa240026a = 20 (score=1000/1000)
read ffffffffa240026b = 25 % (score=1000/1000)
read ffffffffa240026c = 73 s (score=1000/1000)
read ffffffffa240026d = 20 (score=1000/1000)
read ffffffffa240026e = 28 ( (score=1000/1000)
read ffffffffa240026f = 64 d (score=1000/1000)
VULNERABLE
```
- 继续增加读取的字节数,可以得到完整的 `linux_proc_banner` 的内容:`%s version %s ([email protected]) (gcc-12 (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40) %s`

## KASLR

- KASLR: Kernel Address Space Layout Randomization
- 随机化内核地址,避免攻击者猜测出内核地址

## TODO

- Gather data sampling
- Itlb multihit
Expand All @@ -23,7 +74,6 @@ TODO:
- STIBP
- PBRSB-EIBRS
- BHI
- PTI/KPTI
- PTE Inversion
- Retpoline
- IBRS_FW
Expand Down

0 comments on commit 491ff64

Please sign in to comment.