![二进制文件上的 SUID 位仍然产生“权限被拒绝”错误](https://linux22.com/image/120673/%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%96%87%E4%BB%B6%E4%B8%8A%E7%9A%84%20SUID%20%E4%BD%8D%E4%BB%8D%E7%84%B6%E4%BA%A7%E7%94%9F%E2%80%9C%E6%9D%83%E9%99%90%E8%A2%AB%E6%8B%92%E7%BB%9D%E2%80%9D%E9%94%99%E8%AF%AF.png)
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 帖子:
- SETUID 权限被拒绝
- 为什么在使用 system() 调用管理程序的 setuid-root C 程序中需要 setuid(0)?
- 调试 setuid 程序/使用 setuid“权限被拒绝”
- Unix suid 位问题
- 如何在非root用户的程序中设置setuid位?
- linux setuid 不起作用
对于后代,并且因为给定的示例可能有助于在其他情况下诊断此问题或类似问题,所以我在下面保留了原始示例。
您是否可能遇到了错误?我无法在运行 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
组权限访问这些文件。