linux 真实的用户ID、有效用户ID和保存的用户ID之间的差异

rqdpfwrv  于 5个月前  发布在  Linux
关注(0)|答案(5)|浏览(60)

我已经知道 * 真实的用户ID*。它是系统中用户的唯一编号。
在我的系统上,我的uid

$ echo $UID
1014
$

字符串
另外两个ID代表什么?

  • 有效用户ID* 和 * 保存的用户ID* 有什么用,我们在系统中的什么地方使用它们?
lf5gs5x2

lf5gs5x21#

区分真实的和有效的用户id是因为您可能需要临时使用另一个用户的标识(大多数情况下,这将是root,但它可以是任何用户)。(除了把你的话视为理所当然,如果你是X1 M1 N1 X,使用X1 M2 N1 X的特权更改为任何用户)。
因此,真实的用户ID是您的真实身份(拥有进程的人),而有效的用户ID是操作系统用来决定是否允许您执行某些操作的依据(大多数情况下,也有一些例外)。
当您登录时,登录shell会将真实的和有效的用户id设置为密码文件提供的相同值(您的真实的用户id)。
现在,你执行一个setuid程序,除了作为另一个用户运行(例如root),setuid程序还应该代表你做一些事情。这是如何工作的?
执行setuid程序后,它将拥有您的真实的id(因为您是进程所有者)和文件所有者的有效用户id(例如root),因为它是setuid。
这个程序会使用超级用户权限来完成它需要完成的任何事情,然后代表你做一些事情。这意味着,尝试做一些你不应该做的事情 * 应该失败 。它是如何做到的?很明显,通过将其有效的用户ID更改为真实的用户ID!
现在setuid程序没有办法切换回来,因为内核只知道你的id和. * 你的id
。砰,你死了。
这就是保存的set-user id的用途。

wlwcrazw

wlwcrazw2#

我将尝试用一些例子来逐步解释。

短背景

每个进程都有自己的“进程凭证”,其中包括PIDPPIDPGIDsession ID等属性,以及真实的和有效的用户和组ID:RUIDEUIDRGIDEGID
我们会关注这些。

第1部分:了解UID和GID

现在我将使用我的凭据登录到一个shell并运行:

$ grep $LOGNAME /etc/passwd
rotem:x:1000:1000:rotem,,,:/home/rotem:/bin/bash

字符串
你可以看到我的登录名(rotem),UIDGID都是1000,以及其他细节,如我登录到的shell。

第2部分:了解RUID和RGID

  • 每个进程都有一个所有者并属于一个组 *。在我们的shell中,我们现在运行的每个进程都将继承我的用户帐户的权限,并将使用相同的UID和GID运行。

让我们运行一个简单的命令来检查它:

$ sleep 10 & ps aux | grep 'sleep'


检查进程UID和GID:

$ stat -c "%u %g" /proc/$pid/
1000 1000


进程真实的 * 用户IDRUID)和真实的组IDRGID)。
(*)检查other options to view the UID and GIDways to get this in a single line
现在,接受EUIDEGID属性是“冗余”的事实,并且在幕后相当于RUIDRGID

第3部分:了解EUID和EGID

让我们以ping命令为例。
使用which命令搜索二进制位置,然后运行ls -la

-rwsr-xr-x  1 root root   64424 Mar 10  2017  ping


您可以看到文件的所有者和组是root。这是因为ping命令需要打开一个特殊的套接字,而Linux内核需要root权限。
但是,如果我没有root权限,如何使用ping
请注意,在文件权限的所有者部分中,'s '字母代替了'x'。
这是特定二进制可执行文件(如pingsudo)的特殊权限位,称为
setuid

这就是EUIDEGID发挥作用的地方。
当执行一个setuid二进制文件(如ping)时,进程将其有效用户ID(EUID)从默认的RUID更改为这个特殊的二进制可执行文件的所有者,在本例中为-root
这一切都是由这个文件具有setuid位的简单事实完成的。
内核通过查看进程的EUID来决定该进程是否具有特权。因为现在EUID指向root,所以该操作不会被内核拒绝。

注意事项:在最新的Linux版本中,ping命令的输出看起来会有所不同,因为它们采用了Linux Capabilities方法而不是这种setuid方法-对于那些不熟悉的人-请阅读here
第4部分:SUID和SGID如何?

当特权进程正在运行(例如root)并且它需要执行一些非特权任务时,将使用保存的用户ID(SUID)。
在这种情况下,之前的有效UID(EUID)将保存在SUID中,然后更改为非特权任务。当非特权任务完成时,EUID将从SUID的值中取出,并切换回特权帐户。

7y4bm7vi

7y4bm7vi3#

真实的用户ID是生成进程的用户。
有效用户id是由正在执行的二进制文件上的setuid位确定的用户。
以下是一些关于uid和euid的事实,以及每种的手动源代码:
当你以root身份生成时,你可以使用euid,你需要暂时放弃特权,并且仍然能够在之后重新获得root特权,如man setuid(2)所示:

Thus, a set-user-ID-root program wishing to temporarily drop root privileges, as‐
sume the identity of an unprivileged user, and then regain root privileges after‐
ward cannot use setuid().  You can accomplish this with seteuid(2).

字符串
如果你的有效用户名是root,那么所有的操作都将像你是root一样进行,除了我认为唯一的例外是文件访问检查将检查你的真实的用户名而不是有效的用户名,这是一个混淆的来源,就像man access(2):

The check is done using the calling process's real UID and GID,  rather
than the effective IDs as is done when actually attempting an operation
(e.g., open(2)) on the file.  Similarly, for the root user,  the  check
uses the set of permitted capabilities rather than the set of effective
capabilities; and for non-root users, the check uses an  empty  set  of
capabilities.


当调用bash时,它不会传播euid,除非你像man bash(1)那样传递-p

If the shell is started with the effective user (group) id not equal to the  real
user  (group)  id,  and the -p option is not supplied, no startup files are read,
shell functions are not inherited from the environment, the SHELLOPTS,  BASHOPTS,
CDPATH, and GLOBIGNORE variables, if they appear in the environment, are ignored,
and the effective user id is set to the real user id.  If the -p option  is  sup‐
plied  at invocation, the startup behavior is the same, but the effective user id
is not reset.


当使用sudo时,有效的和真实的用户ID都被设置为man sudo(8):

When sudo executes a command, the security policy specifies the execution environ‐
ment for the command.  Typically, the real and effective user and group and IDs are
set to match those of the target user, as specified in the password database, and
the group vector is initialized based on the group database (unless the -P option
was specified).

gg58donl

gg58donl4#

我是这样理解的。用户执行的文件(相当于启动一个进程)将有一个RUID等于该用户的id。这里需要注意的是,创建文件的uid与执行文件的uid是不同的。它们可以相同或不同。因此,RUID可能会根据执行文件的UID而有所不同。当文件上有setuid位时,每当uid执行该文件时,该uid将临时替换为文件所有者的uid。因此,如果我们有一个由uid 456拥有的文件,并且其上具有setuid位,则每当uid 123执行该文件时,该文件将以uid 456执行。在此场景中,uid 123是RUID,uid 456是EUID。

xn1cxnb4

xn1cxnb45#

@Rotem jackoby的回答很好。作为休闲,你可以看到我对这篇文章的回答。它包含一个示例C程序,你可以运行它,亲眼看看Linux中 * 进程 * 的真实的用户ID(RUID),有效的用户ID(EUID)和保存的用户ID(SUID)之间的区别。
在这里我只想指出,所有类Unix系统的官方文档,当然包括Linux,* The Open Group Base Specifications Issue 7,2018 edition*(参见“3.定义”here),指出了RUID的概念,EUID和SUID适用于“当用户的身份与 * 进程 * 相关联时”(参见3.436 User ID here)。换句话说,如果用户没有启动或生成任何进程,那么谈论RUID、EUID或SUID就没有意义,但仅关于用户ID(UID),仅此而已。

相关问题