kernel利用
Linux内核漏洞利用目的:
1、提权==》root(主要)
2、泄漏敏感信息
3、Dos==》内核崩溃
提权:
普通用户获得root权限,访问原先受限的资源==》
改变自身 Chenge Self
通过改变自身进程的权限
内核通过进程的task_struct结构体中的cred指针来索引cred结构体,根据cred的内容判断一个进程的拥有的权限
cred结构体成员uid-fsgid==0==》进程具有root权限
struct cred {
atomic_t usage;
#ifdef CONFIG_DEBUG_CREDENTIALS
atomic_t subscribers; /* number of processes subscribed */
void *put_addr;
unsigned magic;
#define CRED_MAGIC 0x43736564
#define CRED_MAGIC_DEAD 0x44656144
#endif
kuid_t uid; /* real UID of the task */
kgid_t gid; /* real GID of the task */
kuid_t suid; /* saved UID of the task */
kgid_t sgid; /* saved GID of the task */
kuid_t euid; /* effective UID of the task */
kgid_t egid; /* effective GID of the task */
kuid_t fsuid; /* UID for VFS ops */
kgid_t fsgid; /* GID for VFS ops */
...
}
利用方式:
1、cred结构体
直接修改cred结构体内容
1、定位
直接定位:
扫描内存定位
==》在定位过程中,会有很多满足条件的cred==》因为cred结构体可能会拷贝,释放==》
利用usage不为0筛选cred(cred使用rcu延迟释放)
间接定位:
利用task_struct
定位当前进程task_struct结构体地址==》
根据cred指针相对于task_struct结构体的偏移计算cred指针存储地址==》
获取cred具体地址
利用comm
comm使用来标记可执行文件的名字,位于进程的task_struct结构体中
/* Process credentials: */
/* Tracer's credentials at attach: */
const struct cred __rcu *ptracer_cred;
/* Objective and real subjective task credentials (COW): */
const struct cred __rcu *real_cred;
/* Effective (overridable) subjective task credentials (COW): */
const struct cred __rcu *cred;
#ifdef CONFIG_KEYS
/* Cached requested key. */
struct key *cached_requested_key;
#endif
/*
* executable name, excluding path.
*
* - normally initialized setup_new_exec()
* - access it with [gs]et_task_comm()
* - lock it with task_lock()
*/
char comm[TASK_COMM_LEN];
先定位comm==》再定位cred地址
1、修改
1、当有任意地址读写权限==》直接修改cred
2、当可以执行ROP执行代码==》利用ROP gadget修改cred
例:
UAF使用同样的堆块==》
1、申请一块与cred结构体大小相同的堆块
2、释放该堆块
3、fork出新进程==》cred结构体使用该释放的堆块
4、修改cred结构体==》提权
2、cred指针
修改task_struct结构体中的cred指针指向一个满足要求的cred
2、定位
直接定位(不推荐)
间接定位
利用task_struct
定位当前进程task_struct结构体的地址==》
根据cred指针相对于task_struct结构体的偏移计算cred指针存储的位置
利用common
comm在cred指针下方==》通过先定位comm==》再定位cred指针的地址
注意点:在进程名字不特殊的情况下,内核中可能会有多个同样的字符串,会影响搜索的正确性与效率
==》使用prctl设置进程的comm为一个特殊的字符串,再定位comm
2、修改
1、修改cred指针为内核镜像中已有的init_cred的地址(适用于能直接修改cred指针以及知道init_cred地址)
2、伪造一个cred,然后修改cred指针指向该地址(不推荐)
3、commit_creds
使用commit_creds(prepare_kernel_cred(0))来进行提权==》
自动生成一个合法的cred,并定位当前进程的task_struct的位置==》修改它的旧的cred为新的cred
==》适用于控制程序执行流,并且不需要知道cred的地址
改变别人 Change others
通过改变特权进程的执行轨迹
利用方式:
1、改数据
符号链接
一个root权限的进程会执行一个符号链接的程序,并且该符号链接或者符号链接指向的程序可以由攻击者控制
==》提权
call_usermodehelper
call_usermodehelper是一种内核线程执行用户态应用的方式,并且启动的进程具有 root 权限==》
能够控制具体要执行的应用==》提权
call_usermodehelpe具体要执行的应用由某个变量指定==》改变变量
==》修改方式
1、==》修改modprobe_path==》获取modprobe_path地址==》修改modprobe_path指定的程序
==》触发执行call_usermodehelper==》触发方式
==》执行一个非法的可执行文件/使用未知协议触发
===》定位modprobe_path==》
直接定位:modprobe_path取值确定==》直接扫描内存,寻找对应字符串
间接定位:先获取内核基地址,根据相对偏移获得地址
2、==》修改poweroff_cmd==》修改poweroff_cmd为指定的程序==》
劫持控制流执行__orderly_poweroff
==》定位==》类似定位modprobe_path
2、改代码
修改vDSO代码
内核中 vDSO 的代码会被映射到所有的用户态进程中==》
当一个高特权的进程周期性调用vDSO中的函数==》
将vDSO中的函数修改为特定的shellcode==》当高权限的进程执行相应代码==》提权
定位==》
1、IDA中定位==》使用raw_data可知道vDSO在内核镜像中的地址(vDSO以页对齐)
2、内存中定位==》
直接定位:vDSO是一个ELF可执行文件,有ELF文件头,存储着导出函数的字符串==》扫描内存==》定位
间接定位:先获取内核的基地址==》根据偏移获得vDSO地址
DoS
1、触发内核内某个漏洞让内核崩溃
2、触发内核中的死锁
3、触发大量的内核内存泄漏(存在大量的内存被申请但是没有释放)