1

根据手册页issetugid,该调用应该(1)提醒 uid/gid 更改;或 (2) 警惕可能的污染环境。函数名称暗示了第三个目的。

第一个问题:它的目的是什么?

当我查看可用的实现时(例如,在 Linux 系统上作为库,因为 Linux 内核不提供 API),我发现以下内容:

if (getuid() != geteuid()) return 1; 
if (getgid() != getegid()) return 1; 
return 0; 

在 Solaris 上,它如下所示:

return ((curproc->p_flag & SUGID) != 0);

我有点怀疑,但这部分是因为它很难理解在所有平台上喜欢什么函数geteuidgetegid返回——例如,BSD、Linux、Unix 和 Solaris。

第二个问题:Linux 代码在语义上是否等同于 Solaris 代码?

第三个问题:跨平台的实现是否相同geteuidgetegid对于拥有三个身份的系统——真实的、有效的和保存的,怎么样?

第四个问题:有效的身份是唯一重要的身份吗?

如果一个进程以 UID = 0 开始并暂时放弃特权,那么savedid 就会发挥作用。临时删除根的进程不需要也不exec应该被污染。

第五个问题:临时掉根的进程是否被污染?

第六个问题:一个有效id是保存的id的进程是否应该被认为是被污染的?

4

2 回答 2

4

在为一个问题设计的系统中,六个问题的回答有点多,特别是如果没有人知道所有六个问题的答案,但我会尝试......

1) 的目的issetugid()是让库知道它们是否正在以提升的权限运行的程序中使用,这样它们就可以避免风险行为,例如信任 LD_LIBRARY_PATH、NLSPATH 等环境变量,这些环境变量会让调用者加载模块可以滥用提升的权限。你可以看到一些关于它的历史讨论,比如这个ncurses 4.1 security bug thread

2) 该代码似乎不如 BSD 和 Solaris 版本安全,因为它没有考虑保存的 setid 位。

3)他们可能在不同的内核上有不同的实现 - 查看平台源代码以找出答案。

4、5 和 6) 不,是,是 - 可以将其 euid 或 egid 更改回更高级别的进程仍然不应该信任导致它加载用户提供的代码以利用它们的环境变量。

于 2013-05-19T15:26:14.990 回答
2

我不知道issetugid(),但我可以通过阅读 BSD 或 Solaris 手册页来学习。该函数来自 OpenBSD。

1) OpenBSD 的issetugid(2)手册说:“如果进程是 setuid 或 setgid 作为最后一次或其他先前 execve() 系统调用的结果,则 issetugid() 函数返回 1。否则返回 0。” 然后它建议使用 issetugid() 检查环境变量中命名的文件是否可以安全打开。

2) 不,您的 Linux 和 Solaris 代码不等效。运行 setuid 的进程可能会将其真实 uid 设置为其有效 uid,而无需清理其环境变量。例如,uid_t uid = geteuid(); setresuid(uid, uid, uid);将真实 uid 和保存的 uid 都设置为有效 uid。然后你的 Linux issetugid() 将返回 0,但 Solaris issetugid() 将返回 1。

SolarisSUGID在执行时检查进程标志。Illumos 是 Solaris 的免费分支,在执行文件时会在src/uts/common/os/exec.c中设置 SUGID。OpenBSD 也有类似的逻辑。OpenBSD 的手册说,

如果子进程执行一个新的可执行文件,将确定一个新的 issetugid 状态。此状态基于现有进程的 uid、euid、gid 和 egid 权限以及可执行文件的模式。如果新的可执行文件模式是 setuid 或 setgid,或者如果现有进程正在使用 uid != euid 或 gid != egid 执行新映像,则新进程将被视为 issetugid。

Solaris 和 OpenBSD 在执行时比较 id。您的 Linux 代码将比较延迟到调用 issetugid() 之前,因此它是不等价的。

3) geteuid()andgetegid()函数似乎在任何地方都做同样的事情;他们只是返回有效的用户 id 和有效的组 id。

4)保存的ID无关紧要。该进程可能在未清理其环境变量的情况下更改了这些 ID。没有一个真实的、有效的或保存的 id 告诉我们谁为当前进程设置了环境变量。

5) 至少在 OpenBSD 和 Solaris 上,临时删除 root 的进程不会被污染。OpenBSD 的手册页说,

issetugid() 系统调用的结果不受对 setuid()、setgid() 或其他此类调用的调用的影响。在 fork() 的情况下,子进程继承相同的状态。

issetugid() 的状态仅受 execve() 影响。

当进程使用 setuid() 或 seteuid() 临时删除 root 时,它不会执行文件,因此它的 issetugid() 值不会改变。

但 FreeBSD、DragonFly BSD 和 NetBSD 对 issetugid() 的定义更为严格。FreeBSD 的issetugid(2)手册说,

如果一个进程是由于 execve(2) 系统调用的结果而创建的,该系统调用设置了 setuid 或 setgid 位(并因此获得了额外的特权),或者如果它更改了任何真实有效的进程,则该进程被污染或保存的用户或组 ID,因为它开始执行。

在这些系统中,删除根的进程确实会强制其 issetugid() 值为 1。

6) 不,等于保存的 id 的有效 id 不会污染进程。如果是这样,那么每个进程都会受到污染,因为每个进程在执行时都将其保存的 id 设置为其有效 id。

于 2015-05-26T04:40:32.043 回答