这是一个set-root-uid程序
$ls -l
-rwsr-sr-x 1 root root 7406 2011-12-13 22:37 ./x*
源码:
int main(void) {
printf(
" UID GID \n"
"Real %d Real %d \n"
"Effective %d Effective %d \n",
getuid (), getgid (),
geteuid(), getegid()
);
seteuid(600);
printf(
" UID GID \n"
"Real %d Real %d \n"
"Effective %d Effective %d \n",
getuid (), getgid (),
geteuid(), getegid()
);
setuid(1000);
printf(
" UID GID \n"
"Real %d Real %d \n"
"Effective %d Effective %d \n",
getuid (), getgid (),
geteuid(), getegid()
);
setuid(0); // HOW DOES THIS SUCCEED IN SETTING THE EUID BACK TO 0
printf(
" UID GID \n"
"Real %d Real %d \n"
"Effective %d Effective %d \n",
getuid (), getgid (),
geteuid(), getegid()
);
return 0 ;
}
输出
UID GID
Real 1000 Real 1000
Effective 0 Effective 0
UID GID
Real 1000 Real 1000
Effective 600 Effective 0
UID GID
Real 1000 Real 1000
Effective 1000 Effective 1000
UID GID
Real 1000 Real 1000
Effective 0 Effective 1000
我的问题
手册页说明setuid将更改真实的、已保存的和有效的uid。因此,在调用setuid(1000)
之后,这三个函数都更改为1000
。让我把euid
改成0
,setuid(0)
怎么样?
发布于 2011-12-14 12:01:43
DESCRIPTION setuid()设置调用进程的有效用户ID。如果调用者的有效UID是root,则还会设置真实的UID和保存的set-user-ID。
在Linux下,setuid()的实现类似于具有_POSIX_SAVED_IDS特性的POSIX版本。这允许set- user -ID (而不是root)程序删除它的所有用户特权,执行一些非特权的工作,然后以安全的方式重新使用原始的有效用户ID。
如果用户是root,或者程序是set- user -ID-root,则必须特别小心。setuid()函数检查调用者的有效用户ID,如果是超级用户,则将所有与进程相关的用户ID设置为uid。发生这种情况后,程序不可能重新获得root权限。
因此,如果set- user -ID-root程序希望暂时删除root权限,使用非特权用户的身份,然后重新获得root权限,则不能使用setuid()。您可以使用seteuid(2)来完成此操作。
(摘自Linux程序员手册,2014-09-21,第setuid.2
页)
发布于 2011-12-14 13:19:06
不是的!这些函数很难正确使用。
手册页说明setuid将更改真实的、已保存的和有效的uid。因此,在调用setuid( 1000 )之后,这三个参数都更改为1000。
当且仅当您是euid 0时,才会出现这种情况。然而,在调用setuid(0)
时,您是EUID1000并且保存了uid0(例如,检查getresuid(2)
)。这就是为什么你能够重新获得特权。
发布于 2019-04-11 01:00:32
代码:
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
void print_uid(char *str, int ret)
{
uid_t ruid;
uid_t euid;
uid_t suid;
getresuid(&ruid, &euid, &suid);
printf("%s ret:%d\n"
"Real:%4d Effective:%4d Saved:%4d\n",
str, ret, ruid, euid, suid);
}
int main(void)
{
int ret = 0;
print_uid("init", ret); /* Real:1000 Effective: 0 Saved: 0 */
ret = seteuid(600);
print_uid("seteuid(600)", ret); /* Real:1000 Effective: 600 Saved: 0 */
ret = setuid(1000);
print_uid("setuid(1000)", ret); /* Real:1000 Effective:1000 Saved: 0 */
ret = setuid(0);
print_uid("setuid(0)", ret); /* Real:1000 Effective: 0 Saved: 0 */
ret = setuid(1000);
print_uid("setuid(1000)", ret); /* Real:1000 Effective:1000 Saved:1000 */
ret = setuid(0);
print_uid("setuid(0)", ret); /* Real:1000 Effective:1000 Saved:1000 */
return 0 ;
}
sudo chown root setuid_feature
sudo chmod +s setuid_feature
Linux中的进程有三个uid :真正的uid、有效的uid和保存的uid。
条件1.当euid为root时,setuid或seteuid可以设置为任何uid,但有一个副作用,当使用setuid(不是seteuid)时,这三个都可以设置为不是ROOT的同一uid,这样进程就无法重新获得ROOT权限。
条件2.当euid不是root时,setuid或seteuid可以设置为ruid或suid,并且只更改euid。
| seteuid | setuid
Cond 1. (euid == root) | set euid to any uid | set all three uids to any uid
Cond 2. (euid != root) | set euid to ruid or suid | set euid to ruid or suid
因此,代码中有5个setuid或seteuid进程,让我对它们进行分类:
https://stackoverflow.com/questions/8499296
复制相似问题