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

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)

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  
Run Code Online (Sandbox Code Playgroud)

我的问题

手册页指出setuid将改变真实,保存和有效的uid.所以在通话结束后setuid(1000),所有三个都改为1000.那是怎么setuid(0)让我改变euid0

Aja*_*jai 31

有两种情况,

  1. 您希望在执行setuid程序时暂时删除root权限
  2. 您希望在执行setuid程序时永久删除root权限...
  • 您可以通过将euid设置为真实用户ID然后将uid更改为您想要的任何内容来暂时执行此操作.稍后当您需要root权限时,您可以将setuid设置为root,并且有效用户ID将更改回root.这是因为保存的用户ID未更改.
  • 您可以通过直接将uid更改为较低权限的用户ID来永久删除权限.在此之后无论你怎么回事都不能获得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权限.


BRP*_*ock 8

描述 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)


pil*_*row 5

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

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

setuid(0)当且仅当您的 euid 为 0 时才是这种情况。但是,在您调用 时,您的 euid 为 1000 并且保存的uid 为 0(getresuid(2)例如,检查 )。这就是为什么你能够重新获得特权。