重庆思庄Oracle、Redhat认证学习论坛

标题: Linux特殊权限SUID和SGID揭秘 [打印本页]

作者: 梅钟园    时间: 2024-4-10 22:43
标题: Linux特殊权限SUID和SGID揭秘
本帖最后由 梅钟园 于 2024-4-10 23:20 编辑
Linux特殊权限SUID和SGID揭秘
1、SUID和SGID深入剖析
1.1 基础知识 - Linux中的相关系统调用


简单一点(针对UID系列):


       但是对于启用 SUID/SGID 位的程序,EUID 更改为文件所有者/组,而 RUID是启动进程的用户/组。
       要使进程"实际"具有提升权限的操作,仍然需要使用 setuid 系统调用.

setuid(uid) 系统调用,首先请求内核本进程的RUID、EUID、SUID,都设置成函数指定的UID,若权限不足,则仅请求设置EUID为函数指定的UID,再不行,直接调用失败
  规则A: 当具有超级用户权限时,setuid() 对三者均有效
  规则B:否则,仅当ID为RUID或者SUID时,ID对EUID有效
  规则C:否则,直接调用失败

seteuid(uid) 仅请求内核本进程的EUID设置成函数指定的UID

其他系统调用
getuid()        RUID
geteuid()       EUID
getresuid()     SUID


getgid()        RGID
getegid()       EGID
getresgid()     SGID

setgid(gid) 和 setuid() 规则一致

seteuid()       设置EUID
setegid()       设置EGID

setreuid()      交换RUID和EUID
setregid()      交换RGID和EGID

1.2 示例 - SUID 和 SGID
  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>

  5. int main(void) {
  6.   // store uids
  7.   uid_t ruid = getuid();
  8.   uid_t euid = geteuid();
  9.   // store gids
  10.   gid_t rgid = getgid();
  11.   gid_t egid = getegid();

  12.   printf("----------------------------------------------------------------------\n");
  13.   printf("before UID/RUID is: %d ,EUID is: %d\n", ruid, euid);
  14.   printf("before GID/RGID is: %d ,EGID is: %d\n", rgid, egid);
  15.   printf("----------------------------------------------------------------------\n");

  16.   // elevate the privileges -> EUID and EGID
  17.   setuid(euid);
  18.   setgid(egid);

  19.   // perform action
  20.   printf("perform program action ...\n");
  21.   system("id");
  22.   printf("----------------------------------------------------------------------\n");

  23.   // drop privileges -> RUID and RGID
  24.   // the UID and GID can only be changed by the root permissions
  25.   if (setuid(ruid)) {
  26.     fprintf(stderr, "drop user privileges setuid(%d) failed!\n", ruid);
  27.   }else{
  28.     fprintf(stderr, "drop user privileges setuid(%d) success.\n", ruid);
  29.   }
  30.   // permission denied, the most specific permissions take precedence
  31.   // user permissions override group permissions,which override other permissions.
  32.   if (setgid(rgid)) {
  33.     fprintf(stderr, "drop group privileges setgid(%d) failed!\n", rgid);
  34.   }else{
  35.     fprintf(stderr, "drop group privileges setgid(%d) success.\n", rgid);
  36.   }

  37.   printf("----------------------------------------------------------------------\n");
  38.   // end output information
  39.   printf("after UID/RUID is: %d ,EUID is: %d\n", getuid(), geteuid());
  40.   printf("after GID/RUID is: %d ,EGID is: %d\n", getgid(), getegid());
  41.   printf("----------------------------------------------------------------------\n");

  42.   // perform action
  43.   printf("perform program action ...\n");
  44.   system("id");
  45.   printf("----------------------------------------------------------------------\n");
  46.   return 0;
  47. }
复制代码
[user@host]$ gcc -Wall -o process process.c # 编译
[user@host]$ ls -l process*
-rwxr-xr-x. 1 root  root  24760 Apr  9 22:09 process
-rw-r--r--. 1 kiosk kiosk  1994 Apr  9 22:09 process.c
[user@host]$
[user@host]$ sudo chown root:root process
[user@host]$ sudo chmod +sx process # 设置 SUID 和 SGID 权限
[user@host]$
-rwsr-sr-x. 1 root  root  24760 Apr  9 22:09 process
[user@host]$ ./process

上图过程中不难看出,运行 process 时此程序由于设置了SUID和SGID,故而EUID、EGID都是0,有超级管理员用户权限
1.第一次 perform program action 运行 id 命令时得到的是以 root 用户 root 组身份运行。2.在清除SUID特殊权限时,setuid() 由于一开始有超级管理员权限,故而能设置成功,此时身份可以理解为已经变为 kiosk 用户,用户ID为 1000.满足规则A要求
3.再次清除SGID特殊权限时,此时用户身份为 kiosk 用户,不满足规则A要求,所以权限清除失败
上述 2 ~ 3 过程也可以理解为权限优先级,用户上的权限 优先于 组上的权限
最后得到的结果应该是 SUID 特殊权限清除成功,SGID 特殊权限清除失败
4.第二次 perform program action 运行  id 命令时得到以 kiosk 用户 root 组身份运行

1.2 仅 SUID 示例
[user@host]$ sudo chmod g-s process # 去除 SUID 权限
[user@host]$
-rwxr-sr-x. 1 root  root  24760 Apr  9 22:09 process
[user@host]$ ./process

1.第一次 perform program action 运行 id 命令时得到的是以 root 用户 kiosk 组身份运行。
2.在清除SUID特殊权限时,setuid() 由于一开始有超级管理员权限,故而能设置成功,此时身份可以理解为已经变为 kiosk 用户,用户ID为 1000.满足规则A要求
3.再次清除SGID特殊权限时,此时用户身份一直为 kiosk 用户,不满足规则A要求,但满足规则B要求,设置成功
最后得到的结果应该是 SUID 特殊权限清除成功,SGID 特殊权限清除成功,其实也是等于没有清除,一直都是 GID 1000 (kiosk)
4.第二次 perform program action 运行  id 命令时得到以 kiosk 用户 kiosk 组身份运行


其他相关基础知识
1、常见的访问控制模型
直接访问控制(DAC)、强制访问控制(MAC)、基于角色的访问控制(RBAC),此外还有属性访问控制(PAC)、基于策略的访问控制(PBAC)、审计访问控制(AAC)、时间访问控制(TAC)、定位访问控制(LAC)等
典型:

2、直接访问控制(DAC)与 Linux传统UGO模型

3、传统9位基础权限


4、12位权限 - 含特殊权限位
700816616a620b3aeb.png
登录/注册后可看大图