二进制文件上的 SUID 位仍然产生“权限被拒绝”错误

二进制文件上的 SUID 位仍然产生“权限被拒绝”错误

alice并且bob都属于该staff组。

我有以下文件夹:

drwxrwxr-x 2 alice staff 4096 Oct 30 14:45 share

文件夹内有以下文件:

-rwsr-xr-x 1 alice alice 8768 Oct 30 14:45 display-foo
-rw------- 1 alice alice 24 Oct 30 14:45 foo.txt

display-foo是一个二进制foo.txt文件,实质上显示使用该命令的内容cat

alice运行时,二进制文件执行成功并显示./display-foo内容 。foo.txt但是,当bob运行时./display-foo,二进制文件执行成功,但内容foo.txt不显示,产生错误/bin/cat: /home/alice/share/foo.txt: Permission denied


根据我的理解,设置 setuid 位允许以文件所有者的权限执行二进制可执行文件(在本例中为alice)。那么,为什么不允许bob查看 的内容呢foo.txt


附录: 我已经重新编译了二进制使用geteuid()函数来打印出有效用户 ID (EUID)。事实上,当bob执行二进制文件时,EUID 是alice。然而,权限被拒绝。以下是源代码片段:

printf("%d", geteuid());
system("/bin/cat /home/alice/share/foo.txt");

答案1

我通读了手册页对于该system功能,发现以下段落提供了解释:

Do not use system() from a program with set-user-ID or set-group-ID
privileges, because strange values for some environment variables
might be used to subvert system integrity.  Use the exec(3) family of
functions instead, but not execlp(3) or execvp(3).  system() will
not, in fact, work properly from programs with set-user-ID or set-
group-ID privileges on systems on which /bin/sh is bash version 2,
since bash 2 drops privileges on startup.  (Debian uses a modified
bash which does not do this when invoked as sh.)

以下是我在阅读该段落时阅读的其他一些 StackExchange 帖子:

对于后代,并且因为给定的示例可能有助于在其他情况下诊断此问题或类似问题,所以我在下面保留了原始示例。


您是否可能遇到了错误?我无法在运行 Debian 9 和 gcc 6.3 的 Docker 容器中重现您的问题。以下是我如何尝试重新创建您帖子中描述的场景。

首先创建“alice”和“bob”用户并将他们添加到“staff”组:

useradd -m -G staff alice
useradd -m -G staff bob

接下来创建文件并设置其所有权和权限:

# Create a subdirectory to hold the text file
sudo -u alice mkdir -p /home/alice/share/

# Create the text file
sudo -u alice bash -c 'echo "This is foo.txt" > /home/alice/share/foo.txt'

# Set restrictive permissions on the text file
chmod u=rw,g=,o= /home/alice/share/foo.txt

让我们检查一下结果:

$ ls -l /home/alice/share/foo.txt
-rw------- 1 alice alice 16 Nov  4 15:33 /home/alice/share/foo.txt

现在让我们创建一个display-foo使用该system函数的版本:

$ cat <<HEREDOC > /usr/local/src/display-foo.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>

int main(int argc, char **argv) {

    struct passwd *r_pwd = getpwuid(getuid());
    printf("Real user: %s\n", r_pwd->pw_name);

    struct passwd *e_pwd = getpwuid(geteuid());
    printf("Effective user: %s\n", e_pwd->pw_name);

    system("/bin/cat /home/alice/share/foo.txt");
}
HEREDOC

$ gcc /usr/local/src/display-foo.c -o /usr/local/bin/display-foo

让我们设置 的所有权和权限display-foo,包括设置 setuid 位:

chown alice:alice /usr/local/bin/display-foo
chmod u=rwx,g=rx,o=rx /usr/local/bin/display-foo
chmod u+s /usr/local/bin/display-foo

我们还检查一下结果:

$ ls -l /usr/local/bin/display-foo
-rwsr-xr-x 1 alice alice 8640 Nov  4 15:40 /usr/local/bin/display-foo

现在我们运行程序 asalice和 as bob

$ sudo -u alice display-foo

Real user: alice
Effective user: alice
This is foo.txt

$ sudo -u bob display-foo

Real user: bob
Effective user: alice
This is foo.txt

正如您所看到的,看起来一切都按预期进行。

答案2

foo.txt文件位于 中的共享目录中,因此 Bob由于权限原因Alice home directory无法访问 中的文件。Alice home directory您可以在 home 中创建一个目录shared directory,并授予访问该目录的权限。

或者,您可以创建一个shared directory带有groupowner员工的职位,并SGID使用此命令设置位:

chmod 2777 sharedDir

SGID在目录上设置该位时,在原始目录中创建的新文件或子目录将继承该目录的组所有权,而不是基于用户当前的默认组。

因此,当Alice在这里创建文件时,该文件的组所有权将是职员并且该组的所有成员都可以根据staff组权限访问这些文件。

相关内容