我有一个 setuid root 二进制文件,with_sudo.bin
其源代码如下:
/* with_sudo.c */
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
printf("\n\n ruid : %d \n euid : %d \n\n", (int)getuid(), (int)geteuid());
system("/usr/bin/sudo cat /root/key.txt");
return 0;
}
akshay@bluebox ~ $ ls -l with_sudo.bin
-rwsr-sr-x 1 root root 8684 Feb 1 22:09 with_sudo.bin
即使它是一个 setuid root 二进制文件,也会要求输入 sudo 密码。
akshay@bluebox ~ $ ./with_sudo.bin
ruid : 1000 euid : 0
[sudo] password for akshay:
当我运行另一个没有sudo
在 中system()
,它以超级用户权限运行。
/* without_sudo.c */
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
printf("\n\n ruid : %d \n euid : %d \n\n", (int)getuid(), (int)geteuid());
system("cat /root/key.txt");
return 0;
}
akshay@bluebox ~ $ ls -l without_sudo.bin
-rwsr-sr-x 1 root root 8677 Feb 1 22:09 without_sudo.bin
akshay@bluebox〜$ ./without_sudo.bin
ruid:1000 euid:0
:::这是一个秘密密钥:::
当Real UID
使用0
时,二进制文件以超级用户权限运行Effective UID
,setreuid(geteuid(), 0);
而无需提示输入 sudo 密码,尽管sudo
被使用。
/* with_sudo_ruid_elevated.c */
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
setreuid(0, geteuid());
printf("\n\n ruid : %d \n euid : %d \n\n", (int)getuid(), (int)geteuid());
system("/usr/bin/sudo cat /root/key.txt");
return 0;
}
我有读用于EUID
评估进程执行特定操作的权限。那么为什么sudo
RUID
即使出现EUID
了,也会提示输入 sudo 密码0
?
答案1
有点复杂。操作系统核心使用进程的有效 UID 和 GID 来确定其权限/授权;它们用于
- 根据用户/组/其他规则允许/禁止普通文件系统操作(例如打开、链接/取消链接),
- 设置新创建文件的所有权,
- 确定某个进程可以向哪些其他进程发送信号,以及
- 决定进程是否可以挂载和卸载文件系统、更改日期、关闭系统等。
可能还有其他事情。但问题是,当程序需要做出某种访问/授权决定,通常需要使用真实 UID 和 GID。考虑一下:当您的with_sudo.c
程序执行时sudo
,有效 UID 是 root (0),而真实 UID 是您 (1000),如您的printf
。
sudo
但这与从非特权 shell运行时发生的情况完全相同。
每当 sudo
运行时,有效 UID 为 0 – 因此sudo
无法使用它来决定如何操作。它必须使用真实 UID 来确定您到底是谁,这样它才能确定您被允许在 中执行的操作sudo
。只有当真实 UID 为 0 时,它才会sudo
断定您是“真正的”root,或者至少它无法可靠地确定您的真实身份,因此它不知道要对您应用什么限制,它只会执行 而不cat
要求您进行任何进一步的身份验证。