Linux 中各种各样的 uid
Linux 用户 ID
Linux 进程会记录三种用户 ID,分别为 ruid
, euid
和 suid
。
真实用户 ID,ruid
(或者简称为 uid
) 是启动该进程的用户的 ID,每个用户都拥有唯一的 ID。
有效用户 ID(euid
/effective user ID)是系统判断当前进程权限所使用的 ID,在大多数情况下,euid=ruid
。但 SetUID 可执行文件就是一个例外,当一个 SetUID 可执行文件执行时,euid
会被设置为该文件的拥有者。
passwd
就是一个 SetUID 程序,任何用户都可以执行它来修改自己的密码。但修改密码这个操作是一个特权行为。
$ ll /usr/bin/passwd
-r-s–x–x 1 root root 21944 Feb 12 2006 /usr/bin/passwd;
保存用户 ID(suid
,不要与 SetUID 程序弄混),则是用于让一个特权程序放弃自己的权限来进行一些操作,并且在操作完毕后恢复特权状态。
当一个非特权进程修改自身的 euid
时,它只能将 euid
设为 ruid
, euid
或者 suid
当中的值。suid
允许一个普通用户启动一个 SetUID 进程,并且让它降低权限为普通用户,最后仍能返回特权状态。
set*uid
系统调用
int setuid(uid_t uid);
setuid() sets the effective user ID of the calling process. If the calling process is privileged (more precisely: if the process has the CAP_SETUID capability in its user namespace), the real UID and saved set-user-ID are also set.
setuid
通常只修改 euid
,但当调用进程为特权进程时,setuid
会同时设置 suid
与 ruid
。
int setreuid(uid_t ruid, uid_t euid);
int setresuid(uid_t ruid, uid_t euid, uid_t suid);
An unprivileged process may change its real UID, effective UID, and saved set-user-ID, each to one of: the current real UID, the current effective UID, or the current saved set-user-ID. A privileged process (on Linux, one having the CAP_SETUID capability) may set its real UID, effective UID, and saved set- user-ID to arbitrary values.
非特权进程只能将自己的 ruid
,euid
,suid
设置为三者中的其中之一,但特权进程(拥有 CAP_SETUID
特权)可以随意设置自己的 *uid
。
执行程序: execve
与 system
tl;dr
- 如果被执行的程序是 SetUID 程序,则
euid
会被变更为该文件的拥有者,如果不是,则euid
保持不变。 suid
会被设为之前的euid
ruid
保持不变。
bash
bash
具有安全限制,在正常情况下由 SetUID 程序启动 bash
(例如,system("/bin/bash")
),bash
会将自己的 euid
设为 ruid
。可以通过 -p
参数让 bash
保留之前的权限。