在linux进程中会存在两个用户状态,一种是实际用户ID, 一种是有效用户ID

实际用户ID

uid, 就是我是谁,也就是你在操作时候的用户ID, 通常你可以用命令id 来查看自己的信息

>id
uid=1005(raintung) gid=100(users) groups=16(dialout),33(video),100(users)
而通常root 的uid 是0

有效用户ID

euid, 这是控制进程能访问的资源的id,也就是说资源能否访问取决于euid, 通常就是这个执行文件的所有者

通常的情况下,实际用户ID是和有效用户ID是一样的,有效用户ID 应该等于运行进程的用户ID,但如果该文件据有s权限,一切就变的不同了

文件中的S权限

一般我们知道文件的三种权限,read/write/execute 所对应的是读写执行的权限,但是有的时候会有一些特殊的情况,比如有些操作必须是root权限,可是root权限是不会开放给一般的用户,那这个用户怎么去调用这些操作呢?前面定义的有效用户ID, 实际用户ID就是为了解决这一困境,普通用户只要拥有进程的有效用户id 是root, 那么普通用户就可以操作root 权限的操作。

而如何设置这一特殊权限?就是通过设置文件的S权限,也就是setuid,seteuid的权限

如何设置文件的S权限?

chmod u+s uid
ll uid
-rwsr-xr-x 1 root root 12313 Feb 15 23:53 uid
我们看到标志位中多了s,也就是文中一直提到的S权限

用户案例

读取root才能读取的文件

例子:我们去尝试读取一个只有root能访问的文件test

uid.c

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>

int main(void)
{
    printf("uid = %d, gid = %d, euid = %d, egid = %d\n", getuid(), getgid(), geteuid(), getegid());
        if ( open("test", O_RDONLY) == -1) {
                fprintf(stderr, "Open %s Error:%s\n", " file", strerror(errno));
                exit(1);
        }
}

root 编译成可执行文件 uid

gcc -o uid uid.c
./uid
uid = 0, gid = 0, euid = 0, egid = 0

因为 test 文件是root 才能访问,当用root 运行的时候,文件是可以正常执行的

切换非root用户,在运行结果如下

./uid
uid = 1005, gid = 100, euid = 1005, egid = 100
Open  file Error:Permission denied
切换root给uid执行文件据有s权限

chmod u+s uid
切换回非root用户,继续运行

./uid
uid = 1005, gid = 100, euid = 0, egid = 100
文件test 可以正常被非root用户访问了,我们看到了euid=0 也就是root,  此时进程的有效用户是root

把自己变成root

通过函数setuid 可以设置实际用户ID

root.c文件

#include <stdio.h>  
int main(){  
setuid(0);  
execve("/bin/sh",NULL,NULL);  
}  
gcc -o root root.c
chmod u+s root
su use
./root
whoami

root

结果非常强悍,use 用户轻易变成了root,这个用例很眼熟吧,其实就是在栈溢出攻击系列:shellcode在linux x86 64位攻击获得root权限(二)shellcode中提到的opcode代码,这个代码可以让用户变成root,当然这个可执行文件必须据有root 的S权限。







Logo

更多推荐