在做毕设的时候,碰到了一个场景:需要在普通用户的情况下调用“特权程序”,来访问受保护的文件。相应知识网络安全课学过,这里再回忆并总结一下。
<>有效ID与真实ID的关系
在Unix的设计中,进程与多个用户ID和用户组ID相关联,包括如下:
1、实际用户ID和实际用户组ID:标识我是谁,身份的识别,谁运行的程序。也就是登录用户的uid和gid,比如我的Linux以simon登录,在Linux运行的所有的命令的实际用户ID都是simon的uid,实际用户组ID都是simon的gid(可以用id命令查看)。
2、有效用户ID和有效用户组ID:进程用来决定我们对资源的访问权限,权利的识别。一般情况下,有效用户ID等于实际用户ID,有效用户组ID等于实际用户组ID。在操作系统中,用euid表示有效用户id。
当设置(SUID)位时,则有效用户ID等于文件的所有者的uid;同样,如果设置了(SGID)位,则有效用户组ID等于文件所有者的gid。也就是说,不论是哪个用户使用该文件,该文件都拥有等同于其创建者(往往是root)的权限。
进程的RealUID和EffectiveUID 以及进程UID的继承关系
一. 身份的标识: Real UID
* 进程的UID只是泛称, 其实有很多种UID(ruid / euid) * 进程的 Real UID 是进程身份的标识, 用来说明Who am I,
没有实权 * 进程的权限并不是由RealUID来决定的
二. 权限的标识: Effective UID
* 有身份无权限是不行的, 有权限才能为所欲为 * Effective UID 是进程的权利的标识, 标识了该进程的“权利” * Linux的授权 是 靠
Effective UID 来识别的 * 有权利就能做一切 * 之前说明的,文件、资源以及特权API操作权限 是 通过 Effective UID来识别的
三. 身份和权利的关系
* 默认情况下 Real UID == Effective UID, 所以使用ps命令输出的 就是 Effective UID * 我们也可以显示完整的
Effective UID 和Real UID
四. ROOT 用户的特权
* Root 用户, 均是指 Effective UID == ROOT的进程 * 不受任何限制,可以为所欲为 * ROOT进程可以调用setUID
修改自己的Real UID,它也可以把自己的Effective UID改为普通的UID。
五. UID的世袭
* 在Linux世界里,为了安全考虑,UID世袭规则: 身份可以世袭,权利不能世袭 * 子进程的 Real UID = Effective UID, 继承
父进程的Real UID 若父进程的Effective UID 与 Real UID 不一样,则不具有父进程的权利
六、文件的setUID – 文件的setUID标志以及其作用。
临时提升某可执行文件的euid到owner id,同时不需要改变其ruid。这样,普通用户也可以做某些特权行为。
6.1 需求: * Linux的passwd是一个可执行程序, 用于修改用户的密码 *
passwd需要修改多用户的账号文件(该文件仅能ROOT用户可以读写) * 但是 普通用户 也要修改自己的密码 * passwd虽然
是平民身份(由普通用户启动),但是却需要皇族的权限 ---- 身份 和 权利不同 6.2 解决: * 临时提升进程的Effective UID,
而维持身份不变(Real UID), 让他能够利用特权,而又不传给子进程
Readrootfile.c的代码如下:
/* * getuid() returns the real user ID of the calling process. * geteuid()
returns the effective user ID of the calling process. */ #include <stdio.h> #
include <stdlib.h> #include <sys/stat.h> #include <stdio.h> #include <fcntl.h> #
include <pwd.h> #include <grp.h> #include <ctype.h> #include <unistd.h> #include
<sys/types.h> char * get_username_by_id(uid_t uid) { struct passwd *pwd; pwd =
getpwuid(uid); return (pwd == NULL) ? NULL : pwd->pw_name; } int main(int argc,
char *argv[]) { int fd; fd = open(argv[1], O_RDWR); if(fd == -1) perror("Open
fail: "); else printf("Open %s ok.\n", argv[1]); printf("Real User ID:%d,
name=%s\n", getuid(), get_username_by_id(getuid())); /* 如果设置了Set-User-ID(chmod
u+s),那Effective User ID与Owner ID相同。 */ printf("Effective User ID:%d, name=%s\n",
geteuid(), get_username_by_id(geteuid())); close(fd); return 0; }