【问题标题】:How to use setuid() from root to become user, with the possibility of becoming root again later?如何从 root 使用 setuid() 成为用户,以后有可能再次成为 root?
【发布时间】:2010-02-16 18:21:35
【问题描述】:

我正在尝试做安全的事情,并且有一个程序需要以 root 身份运行以在不需要它们时放弃其权限。如果我 chmod 我的二进制文件带有 SUID 位,这很好用,并使其属于 root,因为现在我有 UID = 某个用户,并且 EUID = root,所以我可以使用 seteuid(0)seteuid(getuid()) 分别提高并删除管理员权限。

但是如果我使用sudo 而不是设置SUID,那么UID == EUID == 0,所以调用seteuid(getuid()) 不会有任何效果。而且我不能只是将UID 更改为某个随机用户的某个值,因为setuid() 手册页明确指出,如果从以root 身份运行的程序调用它,则永远失去特权,没有希望让他们回来。

那么,如何让我的程序在使用sudo 运行时暂时失去其权限?

【问题讨论】:

  • 您需要返回运行sudo 的用户的UID,还是只返回一个随机的、权限较低的用户?
  • 我会选择nobody。但如果你知道获取 sudo 调用者的简单方法,我很感兴趣。
  • 嗯,很简单,只需getenv("SUDO_UID")

标签: c linux security root setuid


【解决方案1】:

seteuid(some random uid) 删除权限,seteuid(0) 恢复权限,当以root 运行时。

【讨论】:

  • 当然——这就留下了获取调用sudo的用户的原始UID的问题——如果OP需要返回给那个用户?
  • 当然,您切换到的随机 UID 有可能恰好是系统管理员的 UID。
  • sudo 创建包含调用用户的 UID 和 GID 的环境变量。您可以切换到“无人”读取变量并切换到该用户。我不建议以 root 身份读取环境变量。 “nobody”是大多数 Unix 系统上存在的受限帐户。
【解决方案2】:

似乎 seteuid(x) 应该可以删除并重新提高 privs...

$ cat > t12.c
#include <stdio.h>
#include <unistd.h>

void p(void) { printf("euid=%4d uid=%4d\n", geteuid(), getuid()); }

int main(void) { p(); seteuid(100); p(); seteuid(0); p(); return 0; }
$ cc -Wall t12.c
$ sudo chown root a.out && sudo chmod 4555 a.out
$ sudo ./a.out
euid=   0 uid=   0
euid= 100 uid=   0
euid=   0 uid=   0
$ ./a.out
euid=   0 uid= 501
euid= 100 uid= 501
euid=   0 uid= 501
$ 

【讨论】:

  • 如何确保 uid=100 不在 sudoers 组中?
  • 这只对 sudo 本身很重要。 sudoers 组授予的唯一特权是使用 sudo 命令的能力。它不会使用户 id 具有 root 访问权限。
【解决方案3】:

不是直接回答,只是想向您指出privilege separation的想法。这是 OpenBSD 创始人 Theo de Raadt 的 presentation

【讨论】:

    【解决方案4】:

    Fork() 在你放弃权限之前。在父任务中等待,直到权限降低的子任务完成,然后以 root 权限在父任务中继续。

    seteuid 并非适用于所有 unice,并且还有其他缺点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-08
      相关资源
      最近更新 更多