删除root权限

Dav*_*ven 54 c unix root

我有一个以root身份启动的守护进程(因此它可以绑定到低端口).在初始化之后,我非常希望出于安全原因让它删除root权限.

任何人都可以指出我在C中已知的正确代码片段会这样做吗?

我已经阅读了手册页,我已经在不同的应用程序中查看了它的各种实现,它们都是不同的,其中一些非常复杂.这是与安全相关的代码,我真的不想重新发明其他人犯的错误.我正在寻找的是一个最佳实践,已知良好的,可移植的库函数,我可以使用它知道它将正确.这样的事情存在吗?

供参考:我是从根本上开始的; 我需要改变以在不同的uid和gid下运行; 我需要正确设置补充组; 之后我不需要改回root权限.

Jul*_*ano 46

要删除所有权限(用户和组),您需要在用户之前删除该组.鉴于useridgroupid包含要删除的用户和组的ID,并假设有效ID也是root,这可以通过调用setuid()setgid()来完成:

if (getuid() == 0) {
    /* process is running as root, drop privileges */
    if (setgid(groupid) != 0)
        fatal("setgid: Unable to drop group privileges: %s", strerror(errno));
    if (setuid(userid) != 0)
        fatal("setuid: Unable to drop user privileges: %S", strerror(errno));
}
Run Code Online (Sandbox Code Playgroud)

如果你是偏执狂,你可以尝试恢复你的root权限,这应该失败.如果它没有失败,你就救助:

 if (setuid(0) != -1)
     fatal("ERROR: Managed to regain root privileges?");
Run Code Online (Sandbox Code Playgroud)

此外,如果您仍然偏执,您可能也想要seteuid()setegid(),但它不应该是必要的,因为如果进程由root拥有,setuid()和setgid()已经设置了所有ID.

补充组列表是一个问题,因为没有POSIX函数来设置补充组(有getgroups(),但没有setgroups()).您可以使用BSD和Linux扩展setgroups(),这会让您感到担忧.

您还应该chdir("/")或任何其他目录,以便该进程不会保留在根拥有的目录中.

由于你的问题一般是关于Unix的,所以这是非常通用的方法.请注意,在Linux中,这不再是首选方法.在当前的Linux版本中,您应该在可执行文件上设置CAP_NET_BIND_SERVICE功能,并以普通用户身份运行它.无需root访问权限.

  • 您可以使用`initgroups(3)`重置补充组,它足够便携(至少BSD和GNU libc有它). (3认同)
  • 这确实需要是一个可移植的解决方案,所以恐怕不允许 Linux 功能。我确实尝试过使用 setuid() 和 setgid(); 的简单方法;它没有正确设置组(如果您不调用 setgroups(),显然您最终仍然可能是某些 root 组的成员!)。 (2认同)
  • 始终清除补充组.initgroups存在于AIX,Solaris,HP-UX,FreeBSD,Darwin,Linux以及其他可能的版本中.包含它,以便在无法找到时构建失败.不丢弃所有组可能导致严重的系统损害和CVE.我不认为chdir有任何安全隐患,是吗? (2认同)

小智 16

你正在寻找这篇文章:

POS36-C.在放弃特权时观察正确的撤销顺序

不确定如何最好地在那里放置一些信息而不重复该页面的内容......