Linux 内核漏洞利用 Cheat Sheet
从利用角度看内核结构体(更新中…)
以常见的UAF为例,内核漏洞利用过程中,涉及到的组件比较多。而每个人的理解都不尽相同,导致描述时常常存在歧义或者交流起来比较费劲。所以以我对内核pwn的理解(master wang指导🐶),画了一张图,方便看到这篇文章的人明白我的表述。
这张图从上往下分为用户态和内核态,从左到右分为漏洞侧和利用侧,后两个概念的定义如下:
- 漏洞侧:
漏洞ko
+UAF堆块
。漏洞多出现在漏洞ko
对已free的内核堆块进行读/写/释放。 - 利用侧:
exp
+UAF堆块
。利用多是让exp
通过syscall占用漏洞ko
free的堆块(不同结构体),达到控制流劫持/信息泄露的目的。
可见,对内核UAF漏洞的利用是漏洞ko
(漏洞侧)和exp
(利用侧)之间基于同一个堆块的复杂交互过程。
控制流劫持
当 漏洞ko
仅有 “UAF写” 功能时,让 exp
通过某个系统调用在内核创建一个某种大小的结构体,并占用住UAF堆块
。接下来,通过 “UAF写” 覆盖结构体中的函数指针,就可以达到控制流劫持的目的。
下表列出了当前已知的可以控制流劫持的结构体:
结构体 | 大小 | ko漏洞点 | 利用效果 | 写偏移 |
---|---|---|---|---|
tty_struct | 0x2e0 (kmalloc-1024) | UAF写 | 控制流劫持 | 0x18指向函数指针列表 |
seq_operations | 0x20 (kmalloc-32) | UAF写 | 控制流劫持 | 0x0处函数指针 |
subprocess_info | 0x60 (kmalloc-128) | UAF写 | 控制流劫持 | 0x50处函数指针(race) |
pipe_buffer | 0x280 (kmalloc-1024) | UAF写 | 控制流劫持 | 0x10指向函数指针列表 |
tty_ldisc_ops | 0xa8(kmalloc-192) | UAF写 | 控制流劫持 | 0x38处函数指针,ref |
信息泄露
信息泄露有两种情况:
- 一种是利用 “UAF写” 改变
exp
对应内核结构体的内容(如改变内容指针或内容大小)。从而在exp
再次读取其内容时达到任意地址读/越界读的效果。 - 另一种是利用”UAF读” 直接泄露
exp
对应内核结构体中的内容(如堆地址/内核地址)。
UAF写
可用于 “UAF写” 利用的结构体如下:
结构体 | 大小 | ko漏洞点 | 利用效果 | 写偏移 |
---|---|---|---|---|
ldt_struct | 0x10(kmalloc-16) | UAF写 | 越界读/任意地址读 | 0x0:指向数据区,0x8:大小 |
msg_msg | 非固定 | UAF写 | 越界读/任意地址读 | 0x30:第一段数据区,0x20:指向下一段数据区;0x18:总大小 |
user_key_payload | 非固定 | UAF写 | 越界读 | 0x18:开始是数据区,0x10:大小(2byte) |
UAF读
可用于 “UAF读” 利用的结构体如下:
结构体 | 大小 | ko漏洞点 | 利用效果 | 读偏移 |
---|---|---|---|---|
tty_struct | 0x2e0 (kmalloc-1024) | UAF读 | 泄露堆/内核地址 | 堆:0x8/0x10(multiple);内核:0x18/0x2d0 |
seq_operations | 0x20 (kmalloc-32) | UAF读 | 泄露内核地址 | 内核:0x0/0x8/0x10/0x18 |
subprocess_info | 0x60 (kmalloc-128) | UAF读 | 泄露堆/内核地址 | 堆:0x8/0x30;内核:0x18/0x48/0x50/ |
pipe_buffer | 0x280 (kmalloc-1024) | UAF读 | 泄露内核地址 | 内核:0x10 |
shm_file_data | 0x20 (kmalloc-32) | UAF读 | 泄露堆/内核地址 | 堆:0x10;内核:0x8/0x18 |
msg_msg | 0x31~0x1000 (>= kmalloc-64) | UAF读 | 泄露堆 | 堆:0x20/0x28 |
timerfd_ctx | 0xf0 (kmalloc-256) | UAF读 | 泄露堆/内核地址 | 堆:0x30;内核:0x28 |
特殊结构体
记录一些暂时无法归类的特殊结构体,
(1)cred结构体:只能用于老版本,新版本为cred申请堆的方式变了。暂未确定从哪个版本开始不能用该方法。
结构体 | 大小 | ko漏洞点 | 利用效果 | 偏移 |
---|---|---|---|---|
cred | 0xa8 (kmalloc-192) | UAF写 | root提权 | 0x4-0x20全写成0 |