setuid root 不起作用

Pra*_*nay 3 linux setuid privileges

目标:以 root 身份运行程序(C++ 二进制文件)。同:SetUID 位在 Ubuntu 中不起作用?

并且:为什么 setuid 对可执行文件不起作用?

./a.out 输出:

E: Could not open lock file /var/lib/dpkg/lock - open (13: Permission denied) E: Unable to lock the administration directory (/var/lib/dpkg/), are you root? psurana //output for "whoami" Look below for the code.

ls -l 输出:

-rwsrwxr-x 1 root root 46136 Jun 7 20:13 a.out

编码 :

#include <string>
#include <stdlib.h>
int main(int argc, char *argv[]){
        std::string input = "apt-get install " + std::string(argv[1]);
        system(input.c_str());
        system("whoami");
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

详细信息::编译程序,然后执行chown root:root a.out && chmod u+s a.out。请查看上面的 ls -l 输出。

我仍然没有获得 root 权限,代码中 system("whoami") 的输出是我自己在机器上的用户名。

阅读两个链接的问题并没有让我在任何地方。:(。文件的创建者和所有者都是 root。setuid 位已设置,所以它应该可以工作。文件系统也不是外部的,它是我自己的机器。我怎样才能使它工作?

roa*_*ima 5

如果您像这样更改代码,您可以看到有效和真实的 UID:

#include <string>
#include <stdlib.h>
int main(int argc, char *argv[]){
        system("id");
        system("bash -c id");
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

在我的系统上,这将返回这两行(我已经使用...跳过不相关的组):

uid=1001(roaima) gid=1001(roaima) euid=0(root) groups=1001(roaima),24(cdrom),...,103(vboxsf)
uid=1001(roaima) gid=1001(roaima) groups=1001(roaima),24(cdrom),...,103(vboxsf)
Run Code Online (Sandbox Code Playgroud)

如您所见,原始调用id返回 0(根)的有效 UID,但真正的 UID 仍然是我自己的。这是您所期望的。

但是,您可以看到该bash -c id调用已剥离了有效 UID,因此它不再以 root 身份运行。记录man bash如下:

如果 shell 以不等于实际用户(组)id 的有效用户(组)id-p启动,并且未提供该选项,则不读取启动文件,不从环境继承 shell 功能,则SHELLOPTS, BASHOPTS, CDPATH,和GLOBIGNORE变量,如果它们出现在环境中,将被忽略,并将有效用户 ID 设置为真实用户 ID。如果-p在调用时提供该选项,则启动行为相同,但不会重置有效用户 ID。

所以这里的解决方案应该是包含-p标志。

(您可以了解bashSetuid 位重置其 UID的过程似乎对 bash 没有影响。)

然而,故事到这里还没有结束,因为我知道你会说你没有调用bash. 对您来说不幸的是,这几乎是system()代表您所做的,并且它不允许您指定-p.

strace放弃 root 权限,但这里有足够的strace -f ./a.out输出让你看看发生了什么:

execve("./a.out", ["./a.out"], [/* 44 vars */]) = 0
brk(0)                                  = 0x24f1000
...
clone(child_stack=0, flags=CLONE_PARENT_SETTID|SIGCHLD, parent_tidptr=0x7ffee0d42a1c) = 4619
wait4(4619, Process 4619 attached
 <unfinished ...>
Run Code Online (Sandbox Code Playgroud)

此时子进程启动,准备运行我们的 id

[pid  4619] rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f100eb270e0}, NULL, 8) = 0
[pid  4619] rt_sigaction(SIGQUIT, {SIG_DFL, [], SA_RESTORER, 0x7f100eb270e0}, NULL, 8) = 0
[pid  4619] rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
[pid  4619] execve("/bin/sh", ["sh", "-c", "id"], [/* 44 vars */]) = 0
[pid  4619] brk(0)                      = 0x7f849dd71000
[pid  4619] brk(0)                      = 0x7f849dd71000
...
[pid  4619] clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f849d1d89d0) = 4620
Run Code Online (Sandbox Code Playgroud)

现在我们有一个 shell 正在运行,它将丢弃我们的 Effective UID。接下来,您将看到它启动id命令并将其输出写入stdout

Process 4620 attached
[pid  4619] wait4(-1,  <unfinished ...>
[pid  4620] execve("/usr/bin/id", ["id"], [/* 44 vars */]) = 0
[pid  4620] brk(0)                      = 0x1785000
...
[pid  4620] write(1, "uid=1001(roaima) gid=1001(roaim"..., 149) = 149
uid=1001(roaima) gid=1001(roaima) groups=1001(roaima),24(cdrom),...,103(vboxsf)
...
Run Code Online (Sandbox Code Playgroud)

在这里,您的解决方案是直接使用其中一个exec*()系列,或者包括对 的调用setuid(0),或者配置一个工具,例如sudo允许您直接调用目标程序并且(大概)没有密码。

在这些选项中,我个人会采用sudo解决方案。其作者花了很长时间来确保代码可以安全地抵御(非)有意的特权升级攻击。

  • @ilkkachu 这是一个有趣的观点;一个从我身边经过的人。在我的 Debian 系统上,“/bin/sh”是“/bin/dash”的符号链接,而“dash”(显然总是)会删除权限。我想我可能需要测试一下。 (2认同)