永久删除现代Linux上的root权限

bfa*_*oom 13 linux security root

启动后,我希望我的Linux程序删除root权限并切换到非特权帐户.我在网上找到了各种各样的例子,但对我的要求没有任何规范,特别是:

  1. 这是永久性的下降
  2. (e)uid和(e)gid应切换到非root用户
  3. 只有Linux支持(内核> 2.6.32)
  4. 不需要补充团体

我发现的最好方法是:

uid_t new_uid = ...;
gid_t new_gid = ...;

gid_t rgid, egid, sgid;
if (setresgid(new_gid, new_gid, new_gid) < 0)
{
    perror("setresgid");
    exit(EXIT_FAILURE);
}
if (getresgid(&rgid, &egid, &sgid) < 0)
{
    perror("getresgid");
    exit(EXIT_FAILURE);
}
if (rgid != new_gid || egid != new_gid || sgid != new_gid)
{
    printf("unexpected gid");
    exit(EXIT_FAILURE);
}

if (setgroups(0, 0) != 0)
{
    perror("setgroups");
    exit(EXIT_FAILURE);
}

uid_t ruid, euid, suid;
if (setresuid(new_uid, new_uid, new_uid) < 0)
{
    perror("setresuid");
    exit(EXIT_FAILURE);
}
if (getresuid(&ruid, &euid, &suid) < 0)
{
    perror("getresuid");
    exit(EXIT_FAILURE);
}
if (ruid != new_uid || euid != new_uid || suid != new_uid)
{
    printf("unexpected uid");
    exit(EXIT_FAILURE);
}
Run Code Online (Sandbox Code Playgroud)

我可以将它包装在一个exe中并使用以下内容证明uid和gid的显示是正确的:

ps -eO user,uid,ruid,suid,group,gid,rgid,sgid
Run Code Online (Sandbox Code Playgroud)

该程序无法绑定到特权端口或操纵大多数根拥有的文件,所以这一切都很好.

我还发现了captest程序(包含在libcap-ng-utils中),它验证了该进程没有任何意外的能力(7).

但是,由于安全性是一个问题,我希望我更加确信我已经正确地删除了所有非基本权限.我怎么能确定?

谢谢.

小智 1

DJBernstein 在他的“setuidgid”代码中实现了“规范”的方法,该代码最初用于他的 QMail 程序,现在包含在“daemontools”中。

GNU coreutils 中使用的实际代码是基于 DJB 对程序的描述,其代码可以在此处查看https://github.com/wertarbyte/coreutils/blob/master/src/setuidgid.c