堕落不振功业废,勤耕不辍日月新

Linux setuid和seteuid

C/C++ hailen 21℃

本篇内容是 su部分帐户免密码切换 的衍生篇。在LINUX下有4个UID:RUID(real user id)、EUID(effective user id)、SUID(saved user id)、SUID(set user id),其具体区别如下:

RUID, 用于在系统中标识一个用户是谁,当用户使用用户名和密码成功登录后一个UNIX系统后就唯一确定了他的RUID;
EUID, 用于系统决定用户对系统资源的访问权限,通常情况下等于RUID;
SUID(set user id),用于对外权限的开放。跟RUID及EUID是用一个用户绑定不同,它是跟文件而不是跟用户绑定。
saved uid,这个实际上是一个虚拟概念,其对应的实际上还是RUID和SUID,只是在不同身份之间切换时变成对应的值 。

这里举个例子,比如我们常用的passwd改密码命令,普通用户是可以执行的,大家都知道其有s权限位:

[root@361way ~]# ll  /usr/bin/passwd
-rwsr-xr-x. 1 root root 27832 Jun 10  2014 /usr/bin/passwd

假如现在user1想要改密码,user1的RUID是user1,当其调用passwd命令的时候,其有效身份EUID实际为root ,而set user id 就是对应的前面的passwd上的 s 权限位,而saved uid 是中间态 。这个中间态是怎么理解的呢?

当user1执行平时的大多数命令时,其对应的都是RUID,修改一个文件后,对应文件的属主就是user1。而当其调用passwd这个命令修改密码时(passwd修改完成后会更改/etc/shadow里的值),其临时获取了root权限用于修改自身密码,但他修改完成后/etc/shadow文件的属主还是root ,不是user1,对吧!所以saved uid这个中间态你大值就可以这样理解,平时情况下saved user id = RUID,但在遇到set user id这种情况下,saved user id = EUID 。

下面来一段C代码,可以看下这个ID的变化:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
    printf("real uid is %d
", getuid());
    printf("effective uid is %d
", geteuid());
    getchar();
    if (seteuid(1001) == -1)    /* zzz = 1001 */
    {
        perror("seteuid");
        return -1;
    }
    printf("real uid is %d
", getuid());
    printf("effective uid is %d
", geteuid());
    getchar();
    if (seteuid(0) == -1)       /* root = 1001 */
    {
        perror("seteuid");
        return -1;
    }
    printf("real uid is %d
", getuid());
    printf("effective uid is %d
", geteuid());
    getchar();
}

编译代码, 并把可执行文件的属主改为root, 然后添加上set-user-ID位:

gcc uid.c -o uid
sudo chown root:root uid
sudo chmod u+s uid

执行该程序后,输出如下:

real uid is 1001
effective uid is 0
real uid is 1001
effective uid is 1001
real uid is 1001
effective uid is 0

Linux setuid和seteuid,首发于运维之路

转载请注明:我是IT » Linux setuid和seteuid

喜欢 (0)or分享 (0)