启动后,我希望我的 Linux 程序放弃 root 权限并切换到非特权帐户。我在网上找到了各种示例,但没有符合我的要求的规范,特别是:
- 这是一个永久的下降
- (e)uid 和 (e)gid 都应该切换到非 root
- 仅 Linux 支持(内核 > 2.6.32)
- 不需要补充组
我发现的最佳方法是:
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);
}
我可以将其包装在一个 exe 中,并使用以下方法证明 uid 和 gid 看起来是正确的:
ps -eO user,uid,ruid,suid,group,gid,rgid,sgid
该程序无法绑定到特权端口或操作大多数 root 拥有的文件,所以这一切都很好。
我还发现了captest程序(包含在 libcap-ng-utils 中),它可以验证该进程没有任何意外的功能 (7)。
但是,由于安全性是一个问题,我想更有信心我已经正确地放弃了所有非必要的特权。我怎么能确定?
谢谢。