首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >setuid根不工作

setuid根不工作
EN

Unix & Linux用户
提问于 2017-06-08 03:31:36
回答 2查看 4.4K关注 0票数 4

目标:以根用户身份运行程序(C++二进制)。与:没有在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

“守则”:

代码语言:javascript
复制
#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;
}

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

我仍然没有获得根特权,代码中的系统输出(“whoami”)是我自己在机器上的用户名。

阅读这两个相互关联的问题并没有让我产生任何结果。*文件的创建者和所有者都是root用户。setuid位是设置好的,所以应该可以工作。文件系统也不是外部的,它是我自己的机器。我怎么才能把这事做好?

EN

回答 2

Unix & Linux用户

回答已采纳

发布于 2017-06-08 13:25:30

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

代码语言:javascript
复制
#include <string>
#include <stdlib.h>
int main(int argc, char *argv[]){
        system("id");
        system("bash -c id");
        return 0;
}

在我的系统中,它返回这两行(我使用了.跳过不相关的组):

代码语言:javascript
复制
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)

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

但是,您可以看到,bash -c id调用已经取消了有效的UID,因此它不再以根用户身份运行。这在man bash中有如下记录:

如果外壳是以有效用户(组) id不等于实际用户(组) id启动的,并且不提供-p选项,则不会读取启动文件,外壳函数不会从环境继承,如果SHELLOPTSBASHOPTSCDPATHGLOBIGNORE变量出现在环境中,则忽略它们,并将有效用户id设置为实际用户id。如果在调用时提供了-p选项,则启动行为相同,但有效用户id不会重置。

因此,这里的解决方案应该包括-p标志。

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

但是,故事还没有结束,因为我知道您会说您没有调用bash。不幸的是,这正是system()代表您所做的,并且不允许您指定-p

strace放弃了根特权,但是这里有足够的strace -f ./a.out输出,您可以看到发生了什么:

代码语言:javascript
复制
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 ...>

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

代码语言:javascript
复制
[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

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

代码语言:javascript
复制
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)
...

这里的解决方案是直接使用exec*()系列中的一个,或者包含对setuid(0)的调用,或者配置一个工具(如sudo ),允许您直接调用目标程序,并且(想必)不需要密码。

在这些选项中,我会亲自使用sudo解决方案。该代码的作者花了很长时间来确保代码不受(Un)有意升级的权限攻击的影响。

票数 7
EN

Unix & Linux用户

发布于 2017-06-08 07:33:35

这是一个分两步的过程。

  1. 设置可执行的suid位。
  2. 按照setuid(uid_t uid)调用man setuid

如果你的目的仅仅是-获取,你可能会倾向于使用sudo代替。

票数 3
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/369883

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档