RealUID,保存的UID,有效的UID。 这是怎么回事?

这是一个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 ; } 

OUTPUT

  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 。 那setuid(0)怎么让我把euid 0

有两种情况,

  1. 您希望在执行setuid程序时暂时删除root权限
  2. 您想要执行setuid程序时永久删除root权限…
  • 您可以通过将euid设置为真正的用户ID,然后将uid更改为任何您想要的任何内容来暂时执行此操作。稍后,当您需要root权限时,您可以将setuid设置为root,并将有效用户标识更改回root。 这是因为保存的用户ID没有改变。
  • 您可以直接将uid更改为较低权限的用户标识,从而永久删除权限。 在这之后,不管你拿不到root权限。

情况1:

setuid程序开始执行后

 1.seteuid(600); 2.setuid(1000); 3.setuid(0); 

在这种情况下,root权限可以重新获得。

  +----+------+------------+ | uid|euid |saved-uid | |----|------|------------| 1.|1000| 0 | 0 | 2.|1000| 600 | 0 | 3.|1000| 1000 | 0 | 4.|1000| 0 | 0 | | | | | +------------------------+ 

案例2:

在setuid程序开始执行之后

 1.setuid(1000); 2.setuid(0); +----+------+------------+ | uid|euid |saved-uid | |----|------|------------| 1.|1000|0 | 0 | 2.|1000|1000 | 1000 | | | | | +------------------------+ 

在这种情况下,您无法取回root权限。 这可以通过以下命令来验证,

cat / proc / PROCID / task / PROCID / status | 减

 Uid: 1000 0 0 0 Gid: 1000 0 0 0 

这个命令将显示一个UID和GID,它将有4个字段(前三个字段是我们所关心的)。 像上面的东西

这三个字段代表uid,euid和saved-user-id。 您可以在setuid程序中引入暂停(来自用户的输入)并检查每个步骤cat /proc/PROCID/task/PROCID/status | less cat /proc/PROCID/task/PROCID/status | less命令。 在每个步骤中,您可以检查保存的uid是否如前所述进行了更改。

如果您的euid是root用户,并且您更改了uid,则权限将被永久删除。如果有效的用户标识不是root,那么保存的用户标识将不会被触及,您可以随时在程序中重新获得root权限。

描述 setuid()设置调用进程的有效用户标识。 如果调用者的有效UID是root,则也设置真实的UID和保存的set-user-ID。

在Linux下,setuid()与_POSIX_SAVED_IDS特性一样被实现为POSIX版本。 这允许设置用户ID(非root用户)删除所有用户权限,执行一些无权限的工作,然后以安全的方式重新获得原始的有效用户ID。

如果用户是root或程序是set-user-ID-root,那么必须特别小心。 setuid()函数检查调用者的有效用户标识,如果它是超级用户,则所有与进程相关的用户标识都设置为uid。 发生这种情况之后,程序不可能重新获得root权限。

因此,一个希望临时删除root权限的set-user-ID-root程序,假定非特权用户的身份,然后重新获得root权限,之后不能使用setuid()。 你可以用seteuid(2)完成这个。

(从Linux程序员手册,2014-09-21,第setuid.2页)

哦! 这些功能很难正确使用。

手册页指出,setuid将改变真实的,保存的和有效的uid。 所以在调用setuid(1000)之后,所有三个变为1000。

如果且仅当你是euid 0,情况就是这样。然而,当你调用setuid(0)时候,你是euid 1000并且保存了 uid 0(例如检查getresuid(2) )。 这就是为什么你能够恢复特权。