2

我偶然发现了一个关于使用suid可执行文件访问系统文件的问题。

我写了这个简短的 POC:

#include <unistd.h>
#include <stdio.h>

int main()
{
    if (access("/etc/shadow", W_OK) == 0)
        printf("shadow writable!\n");
    else
        printf("shadow not writable\n");

    return 0;
}

然后我编译并用chown root:rootchmod u+s (由root运行)给它suid

这是生成的可执行文件

-rwsrwxr-x  1 root root     4847 Apr 14 08:40 a.out

目标文件有这些权限

-rw------- 1 root root 1836 Oct  8  2014 /etc/shadow

当我运行程序时,它给出了以下输出:

[d.berra@srvr ~]$ ./a.out
shadow not writable

为什么会这样?我的意思是...我正在访问该文件,root并且可以在该文件上root 写入

注:selinux已禁用

想法?

4

3 回答 3

3

来自access

检查是使用调用进程的真实UID 和 GID 完成的,而不是在实际尝试对文件进行操作(例如,open(2))时使用的有效 ID。这允许 set-user-ID 程序轻松确定调用用户的权限。

所以你可以成功打开这个文件进行写入,因为你的有效UID和文件系统UID现在都是0,但是访问仍然会返回错误。

正如@nos 所指出的,您忘记将可执行所有者更改为root

$ sudo chown root:root ./a.out

但即使你这样做,由于access行为,你仍然会得到“不可写”:

$ ls -l ./a.out 
-rwsr-xr-x 1 root root 12651 Apr 14 09:53 ./a.out
$ ./a.out 
shadow not writable
于 2015-04-14T06:58:23.720 回答
2

您设置了 suid 位,这意味着可执行文件将以拥有可执行文件的用户身份运行。可执行文件将作为 运行d.berra,无法写入/etc/shadow.

如果您希望可执行文件以 root 身份运行而不考虑运行它的用户,那么除了设置 suid 位之外,可执行文件还应该归 root 所有。

于 2015-04-14T06:58:29.480 回答
1

试试这个:

#include <unistd.h>
#include <stdio.h>

int main()
{
    setuid(0);

    if (access("/etc/shadow", W_OK) == 0)
        printf("shadow writable!\n");
    else
        printf("shadow not writable\n");

    return 0;
}

它将用户 ID 设置为 root 以便能够访问该文件。setuid(0) 仅适用于有效用户 ID 也为 0 的情况。

于 2015-04-14T07:59:41.173 回答