ruid、euid、suid区分¶
- 参考
- 参考2
- 解释:
ruid (real uid)
:实际用户 ID 其实就是当前登录系统的用户 ID, 是那个运行程序的用户。euid (effective uid)
:有效的用户 id,可以由 c 接口 seteuid 或者 setuid 等修改。这个 euid 是用来做权限校验的,比如访问其它文件时,对比的就是 euid。suid (saved set-user-ID)
:保存的设置用户 ID,可以理解成保存着最初 euid 的状态(seteid 影响),- 规则:
- 通常 ruid、euid、suid 是相等的。
-
通过
chmod u+s
或者chmod o+s
修改可执行文件的 suid,sgid(+s
对 other 位是没有作用的), 可执行位为S
。当修改了可执行文件的 suid 时,任意用户执行此可执行文件,其 euid 和 suid 变成了设置的 uid,而不再是执行程序的用户,ps 显示的用户也设置的用户。 -
示例
$ ll test.sh -rwxr-xr--. 1 shuhw shuhw 0 6月 16 13:53 test.sh $ chmod o+s test.sh $ ll test.sh -rwSr-xr--. 1 shuhw shuhw 0 6月 16 13:53 test.sh
1 Experiments¶
First, let’s create one C file named test.c
, as below:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
uid_t ruid, euid, suid;
getresuid(&ruid, &euid, &suid);
printf("EUID: %d, RUID: %d, SUID: %d\n", ruid, euid, suid);
system("cat file-read-only-by-root"); // file-read-only-by-root: -r-------- root root
setreuid(geteuid(), geteuid());
getresuid(&ruid, &euid, &suid);
printf("EUID: %d, RUID: %d, SUID: %d\n", ruid, euid, suid);
system("cat file-read-only-by-root"); // file-read-only-by-root: -r-------- root root
return 0;
}
gcc -o test test.c
sudo chown root:ubuntu test # Here ubuntu is the normal user
Without setting setuid bit, the result of executing test
is as below:
$ ./test
EUID: 1000, RUID: 1000, SUID: 1000
cat: file-read-only-by-root: Permission denied
EUID: 1000, RUID: 1000, SUID: 1000
cat: file-read-only-by-root: Permission denied
Then we setuid for test file and execute it again,
sudo chmod u+s test
$ ./test
EUID: 1000, RUID: 0, SUID: 0
cat: file-read-only-by-root: Permission denied
EUID: 0, RUID: 0, SUID: 0
Testing
From digging deeply, we find out the problem in the first system("cat file-read-only-by-root")
is that Bash Script bans the setuid option. However, if we directly use fopen->fread
or open->read
, it would be fine. The new C file is as follows:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#define BUFF_SIZE 100
void read_file() {
FILE *fp;
char buffer[BUFF_SIZE];
/* Open file for both reading and writing */
fp = fopen("file-read-only-by-root", "r");
/* Read and display data */
fread(buffer, BUFF_SIZE - 1, sizeof(char), fp);
printf("%s\n", buffer);
fclose(fp);
}
int main()
{
uid_t ruid, euid, suid;
getresuid(&ruid, &euid, &suid);
printf("EUID: %d, RUID: %d, SUID: %d\n", ruid, euid, suid);
read_file(); // file-read-only-by-root: -r-------- root root
setreuid(geteuid(), geteuid());
getresuid(&ruid, &euid, &suid);
printf("EUID: %d, RUID: %d, SUID: %d\n", ruid, euid, suid);
read_file(); // file-read-only-by-root: -r-------- root root
return 0;
}
Then we add setuid option and test again,
$ ./test
EUID: 1000, RUID: 0, SUID: 0
Testing
EUID: 0, RUID: 0, SUID: 0
Testing