Lel*_*uge 36 linux privileges setuid
这是一个set-root-uid程序
$ls -l
-rwsr-sr-x 1 root root 7406 2011-12-13 22:37 ./x*
Run Code Online (Sandbox Code Playgroud)
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 ;
}
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
手册页指出setuid将改变真实,保存和有效的uid.所以在通话结束后setuid(1000),所有三个都改为1000.那是怎么setuid(0)让我改变euid的0?
Aja*_*jai 31
有两种情况,
- 您希望在执行setuid程序时暂时删除root权限
- 您希望在执行setuid程序时永久删除root权限...
情况1:
setuid程序开始执行后
1.seteuid(600);
2.setuid(1000);
3.setuid(0);
Run Code Online (Sandbox Code Playgroud)
对于这种情况,可以再次获得root权限.
+----+------+------------+
| uid|euid |saved-uid |
|----|------|------------|
1.|1000| 0 | 0 |
2.|1000| 600 | 0 |
3.|1000| 1000 | 0 |
4.|1000| 0 | 0 |
| | | |
+------------------------+
Run Code Online (Sandbox Code Playgroud)
案例2:
setuid程序开始执行后,
1.setuid(1000);
2.setuid(0);
+----+------+------------+
| uid|euid |saved-uid |
|----|------|------------|
1.|1000|0 | 0 |
2.|1000|1000 | 1000 |
| | | |
+------------------------+
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您无法取回root权限.这可以通过以下命令验证,
cat/proc/PROCID/task/PROCID/status | 减
Uid: 1000 0 0 0
Gid: 1000 0 0 0
Run Code Online (Sandbox Code Playgroud)
此命令将显示一个Uid和Gid,它将有4个字段(前三个字段是我们关注的字段).像上面这样的东西
这三个字段代表uid,euid和saved-user-id.您可以在setuid程序中引入暂停(来自用户的输入)并检查cat /proc/PROCID/task/PROCID/status | less命令的每个步骤.在每个步骤中,您可以检查已保存的uid如上所述进行更改.
如果您的euid是root并且您更改了uid,则永久删除权限.如果有效用户ID不是root,则永远不会触及已保存的用户ID,您可以随时在程序中重新获得root权限.
描述 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)
哦!这些功能很难正确使用。
手册页指出 setuid 将更改真实的、保存的和有效的 uid。所以在调用setuid(1000)之后,这三个都变成了1000。
setuid(0)当且仅当您的 euid 为 0 时才是这种情况。但是,在您调用 时,您的 euid 为 1000 并且保存的uid 为 0(getresuid(2)例如,检查 )。这就是为什么你能够重新获得特权。