Kernel利用
2022-03-23 18:16:47

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、触发大量的内核内存泄漏(存在大量的内存被申请但是没有释放)