setuid(0)无法执行属于root的程序

3

我需要写一些代码,可以获取root权限并执行系统级操作。以下是我写的代码(这不是实际代码,只是为了测试我是否做得正确):

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
    int current_uid = getuid();
    printf("My UID is: %d. My GID is: %d\n", current_uid, getgid());
    system("/usr/bin/id");
    if (setuid(0))
    {
        perror("setuid");
        return 1;
    }
    //I am now root!
    printf("My UID is: %d. My GID is: %d\n", getuid(), getgid());
    system("/usr/bin/id");
    //Time to drop back to regular user privileges
    setuid(current_uid);
    printf("My UID is: %d. My GID is: %d\n", getuid(), getgid());
    system("/usr/bin/id");
    return 0;
}

在执行gcc -o setuid setuid.c之后,我在其上运行了ls -al,得到了以下结果:
tarun@staging:~$ ls -al setuid
-rwxr-xr-x 1 tarun tarun 9792 2009-10-03 18:09 setuid
adam@staging:~$

尝试运行应用程序会导致以下结果:
tarun@staging:~$ ./setuid
My UID is: 1000. My GID is: 1000
uid=1000(tarun) gid=1000(tarun) groups=1000(tarun),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),109(lpadmin),125(sambashare),999(bumblebee)
setuid: Operation not permitted

我将所有者更改为root,并相应地设置粘滞位:

tarun@staging:~$ su - root
Password:
staging:~# cd /home/tarun
staging:/home/tarun# chown root.root setuid
staging:/home/tarun# chmod +s setuid
staging:/home/tarun# ls -al setuid
-rwsr-sr-x 1 root root 9792 2009-10-03 18:09 setuid
staging:/home/tarun# exit
logout
tarun@staging:~$

现在执行程序会得到以下结果:

adam@staging:~$ ./setuid
My UID is: 1000. My GID is: 1000
uid=1000(tarun) gid=1000(tarun) groups=1000(tarun),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),109(lpadmin),125(sambashare),999(bumblebee)
setuid: Operation not permitted

尽管理想情况下应该完全执行并将我的uid更改为0。我做错了什么?

1
我觉得你的文件是从2009年的有点奇怪,不过,你所遵循的步骤应该是可行的,实际上,在我的机器上也起作用了。 - Rafael Almeida
@Rafael 我猜这可能是我的系统出了问题。我会看看能否找出问题所在。 - Tarun Verma
检查挂载的输出以查看是否启用了suid。也许该分区已经使用nosuid挂载。 - Rafael Almeida
1
谢谢,结果发现我正在使用的文件系统是 ecryptfs 类型,它强制执行 nosuid 和 nodev 以避免特权升级攻击。我不认为我可以关闭它。有什么解决方法吗? - Tarun Verma
添加了一个链接,它应该可以帮助你驯服eCryptFS。 - Roman Nikitchenko
3个回答

5

您的代码没有问题,只需要检查正确的 setuid / 'sgid' 序列:


sudo chmod 6775 setuid
sudo chown root:root setuid

您必须至少设置SUID、SGID和执行权限(6555掩码)。对于此情况,通常还要设置用户/组写入权限(6775掩码)。当然,为了安全起见,您可以将其限制为用户写入掩码(6755)。

请确保在重新编译过程中不要丢失权限:

$ ls -al
-rwsrwsr-x 1 root  root  8772 Feb  8 17:52 setuid

以防你(或未来读者)需要这样的指南: 什么是 SUID 以及如何在 Linux/Unix 中设置 SUID?

关于 eCryptfs 的问题:这里有一篇文章可以帮助你:https://wiki.archlinux.org/index.php/ECryptfs


我感谢您的回答,但它仍然无效。 ls -al 产生了期望的输出,但 ./setuid 仍然不能给我root权限 :-/ - Tarun Verma
请检查UID和SGID。您不在0组中。 - Roman Nikitchenko

1
“粘着位”有完全不同的功能。在文件上,这个位现在基本没有定义,而在目录上,它可以防止非所有者(除root外)删除目录中的文件,无论目录权限如何。
您正在寻找设置UID位:
  chown root setuid
  chmod +s setuid

显然,您必须是root用户才能为属于root的文件设置SUID权限。但由于存在setUID位,我怀疑您可能正在做不必要的努力。


0

更改

chown root.root setuid

chown root setuid

或者

chown root.tarun setuid

1
注意:某些文件系统在挂载时需要设置setuid允许选项。为了允许setuid操作,请检查您的挂载点。 - jim mcnamara

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接