我尝试以 root 身份执行 C++ 编译的程序,而我是另一个用户。
程序已成功执行,但是以普通用户身份执行,而不是root用户。
但是,正如互联网所说,chmod u+s
命令使其以所有者身份运行(在我的情况下是 root)。
程序是一行简单的system(argv[1])
程序,它将执行命令行参数内的所有内容。
例如 - 输出whoami
返回我的用户,而不是根。
还尝试列出/root
最终“权限被拒绝”的内容。
文件的权限 -
-rwsr-xr-x 1 root root 16608 Aug 25 15:20 test
此刻我试图授予该文件的权限4755
(但没有成功)。
移动文件/root
也不太顺利。
答案1
system() 调用使用execl()
系统调用来创建一个新的 shell 进程。但是系统调用忽略了有效用户 ID 并返回 EPERM 错误(权限被拒绝)。
这是因为 Linux Shell 不会继承 seteuid 位。为什么?因为人们确实担心以 root 身份运行具有有效用户 ID 的脚本。有关该主题的更多阅读,请参阅这里。
通过传递参数,可以运行一个作用于有效 UID 的 shell -p
。从sh
手册页中可以看到:
-p 私有 如果有效 uid 与 uid 不匹配,请勿尝试重置有效 uid。默认情况下不设置此功能,以帮助避免 setuid root 程序通过 system(3) 或 popen(3) 进行错误使用。
当然,此限制不适用于系统调用。作为演示,此 C 程序尝试使用 列出 /root system()
,然后使用opendir()
和readdir()
系统调用执行相同操作。
如果二进制文件由 root 拥有,并且设置了用户 ID,则非 root 用户运行该程序将导致第一个 /root 列表失败,第二个(使用display_dir()
有效)。
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<dirent.h>
#include<errno.h>
int display_dir(const char *dirname)
{
DIR *dp = opendir(dirname);
struct dirent *sd=NULL;
if (!dp) return(errno);
while ((sd = readdir(dp)) != NULL)
{
printf("%s\n", sd->d_name);
}
closedir(dp);
return 0;
}
int main()
{
system("ls /root");
printf("Display returned %d\n", display_dir("/root"));
}