最常见的内核漏洞
- NULL pointer dereference
- kernel space stack overflow
- kernel slab overflow
- race conditions
一些漏洞利用比较简单,不需要准备Linux Kernel调试环境来写exploit,另外一些漏洞则需要Linux Kernel设计、工作原理和内存管理等方面的知识。
Kernel Expoit Mitigations
1.内核中与用户空间相同的防御措施:
- DEP(存在)
- Canary(存在)
- ASLR(存在但是有限制)
- PIE(不能直接使用)
- RELRO(不能直接使用)
2.内核中新的防御措施:
- MMAP_MIN_ADDR:mmap_min_addr是用来对抗null pointer dereference的,它不允许程序分配低内存.
- KALLSYMS:/proc/kallsyms给出内核中所有symbol的地址,我们需要这个信息来写可靠的exploit,否则需要自己去泄露这个信息。kallsyms以前是全局可读的,现在它给没有权限的用户返回0.
- RANDSTACK
- STACKLEAK
- SMEP/SMAP
SMEP:Supervisor Mode Execution Protection
SMAP:Supervisor Mode Access Protection
privilege escalation
1.在内核态调用commit_creds(prepare_kernel_cred(0)),返回用户态执行起shell:
1 | void get_r00t() { |
SMEP防预这种类型的攻击的方法是:如果处理器处于ring0
模式,并试图执行有user
数据的内存时,就会触发一个页错误。
SMAP工作原理相同,但是通常是在访问数据时。
这阻止不了漏洞,但会给开发exploit增加大量工作。
2.patch thread_info->addr为0xFFFFFFFF,突破内核地址空间的界限,得到任意读写的权限,然后改写struct cred。
参数传递
x86 Linux内核参数传递顺序有两种方式:
eax
,edx
,ecx
, 栈传递- 直接栈传递
系统调用
经常需要在内核中查找系统调用的定义,比如shmget
,在老版本内核中,系统调用通常定义为sys_shmget
,可以直接通过相关符号查找。但新版本内核中,系统调用方式不同,采用了SYSCALL_DEFINE3(shmget...)
的定义方式,其中3表示shmget有3个参数,参数的个数可以通过查看include/linux/syscalls.h
文件中的定义得到。由于各系统调用的实现比较分散,查找时可以通过grep -nr "SYSCALL_DEFINE3(shmget" .
在Linux内核源码中查找。