如果您为具有执行权限的文件权限添加 setuid 位,它会将 更改为 ,这x
意味着s
如果您执行该文件,它将作为文件的所有者而不是实际执行它的人执行。
但我还注意到,如果您添加s
权限但删除x
权限,它会在权限列表中变为S
。不知何故,这意味着它无法执行,但如果可以执行,它将同时作为所有者执行?对吗?
我误解了这个权限吗?它有什么用?它是什么意思?
答案1
如果设置了 setuid,但用户权限不包括执行,则输出会显示S
。但是,只要组或其他用户能够执行,setuid 位就有意义:如果所有者以外的人执行该文件,它将以所有者的身份运行,这是 setuid 的预期目的。如果所有者可以执行该文件,则它无论如何都会以他们的用户身份运行,因此 setuid 与所有者无关。
这是一个简单的例子:
$ cp $(which whoami) foo
$ sudo chmod u=rs,go+x foo
$ stat -c %A foo
-r-Sr-xr-x
$ ./foo
zsh: permission denied: ./foo
$ sudo -u www-data whoami
www-data
$ sudo -u www-data ./foo
muru
答案2
全部四种组合都存在并且有意义。
“该文件的实际所有者可以运行它吗?”和“系统会假装谁在运行这个文件?”是两个独立的问题。这四种组合都是可能的,并且有意义。
ls -l
或显示的权限字符串stat -c %A
在所有者执行位置(即 中的位置?
)---?------
显示四个不同的字符,每个组合一个:
-
意味着所有者不能运行该文件,如果非所有者运行它,它将运行与其他用户一样。x
意味着所有者能运行该文件,如果非所有者运行它,它将运行与其他用户一样。S
意味着所有者不能运行该文件,如果非所有者运行它,它将运行作为主人。s
意味着所有者能运行该文件,如果非所有者运行它,它将运行作为主人。
setuid 位和执行位是单独的位,模式细绳实际上只是查看权限位(包括这些)的一种方便方式。另一种思考方式是:
x
或s
表示执行位已设置。-
或S
表示未设置。s
或S
表示 setuid 位已设置。-
或x
表示未设置。
类似地,组可能对文件具有或不具有执行权限,并且如果执行,则该文件可能以与运行该文件的用户不同的组身份运行,也可能不以不同的组身份运行。要使文件以其组所有者的组身份而不是运行该文件的用户的组身份运行,您可以设置setgid 位(------s---
或者------S---
)。
S
不代表单独的模式位。它只是表示 setuid(或 setgid)位已设置但相应的可执行位未设置的一种方式。
$ touch foo
$ chmod u+S foo
chmod: invalid mode: ‘u+S’
Try 'chmod --help' for more information.
您可以检查这些位本身。
要查看这些是单独的位,请使用%a
格式说明符stat
而不是%A
。为了简化操作,我取消了所有其他模式位的设置。
$ touch a b c d
$ chmod u=,g=,o= a
$ chmod u=x,g=,o= b
$ chmod u=s,g=,o= c
$ chmod u=xs,g=,o= d
$ stat -c '%A %n' a b c d
---------- a
---x------ b
---S------ c
---s------ d
$ stat -c '%04a %n' a b c d
0000 a
0100 b
4000 c
4100 d
这很清楚...如果你愿意八进制如果你想看二进制(他们是 位毕竟)你可以转换表示形式:
$ stat -c '%a %n' a b c d | perl -pe 's/\d+/sprintf("%012b", oct($&))/e'
000000000000 a
000001000000 b
100000000000 c
100001000000 d
Setuid设置的是有效用户ID,而不是真实用户ID。
执行位控制是否尝试运行一个文件可能会成功,而 setuid/setgid 位控制新进程在允许创建时以谁的身份运行。因此,权限组合S
( -x,+s
) 所代表的并没有什么不一致或令人惊讶的。即使一个可执行文件以其所有者身份运行,因为它的所有者确实运行了它,与一个可执行文件以其所有者身份运行,因为有人运行了它,但它是 setuid,情况也是如此。但事实并非如此。
内核使用多个数字来跟踪正在运行的进程的用户身份。其中一个数字是 UID,另一个是 EUID。请参阅本文有关详细信息。setuid 位会导致 EUID(有效用户 ID)发生更改,但 UID(实际用户 ID)保持不变。它的一个用途是允许在共享 UID 但具有不同 EUID 的进程之间交换信号,但另一个用途是允许设计为将其 setuid 位设置为检查是谁运行的。
例如,passwd
必须是 setuid,因为只有 root 可以更改密码数据库中的条目:
$ ls -l "$(command -v passwd)"
-rwsr-xr-x 1 root root 54256 May 16 19:37 /usr/bin/passwd
-rwsr-xr-x
最后r-x
,对于其他的。由于x
,即使不是 root 或不在 root 组中的用户也可以运行passwd
。并且它rws
在开头附近,对于所有者。由于s
,即使非所有者运行该程序,它也会以 root 身份运行。但是当您passwd
自己运行时,它会重置您的密码,而不是 root 的密码。
passwd
是有能力的因为它以 root 的有效用户 ID 运行,所以它不会对用户和密码数据库进行任何更改。但它被设计为拒绝更改除运行它的用户之外的任何人(除非该用户是 root)的密码,因为它会检查其真实用户 ID。
这是 setuid 可执行文件的典型用例:创建一个接口,允许一个用户以另一个用户的身份执行操作,以由 setuid 可执行文件的代码检查的有限方式执行。因此,只有在以下程序上设置 setuid 位(或 setgid 位)才是安全的:设计拥有这些权限。
S
这是理解为什么权限的含义不再是谜的另一个谜:setuid 位赋予的权力没有与以所有者身份实际运行程序的效果相同,即使程序已被允许运行。
使用副本检查 UID 和 EUID 来id
展示 setuid 的工作原理。
好的,我将在一个非为此设计的可执行文件上设置 setuid 位,以显示真实和有效用户 ID 受到怎样的影响。
- 可执行文件将是复印件的
id
程序,除其他外,报告其真实和有效用户 ID。虽然此程序并非设计为 setuid,但它也不旨在更改任何内容(除了生成输出),因此这相当安全。但您之后仍应将其删除。(您的副本。不是原件。) - 我们正在使用副本,不是更改原始文件的权限。不是
sudo
为此,需要使用或以 root 身份执行任何操作。 - 要以另一个用户身份运行它,您需要第二个用户帐户,但您可以使用它
su
来执行如下操作:那用户。(默认情况下,该root
帐户不允许您使用密码登录,因此如果您犯了一个错误并su
在没有提供要切换到的用户名的情况下运行,您最终不会意外地成为 root,除非您还启用了 root 登录。但是,如果您确实想使用而不是,那么您可以。)sudo -u user
su user -c
我的主要用户帐户名为ek
,我的第二个帐户名为ek2
。如果您的帐户不同,也没关系。首先,作为ek
,我将文件复制id
到当前目录(位于我的主目录中的某个位置):
$ type -a id
id is /usr/bin/id
$ cp /usr/bin/id .
该副本拥有复制它的非 root 用户的所有权,但具有原始权限:
$ ls -l id /usr/bin/id
-rwxr-xr-x 1 ek ek 39760 Oct 5 11:23 id
-rwxr-xr-x 1 root root 39760 Mar 2 2017 /usr/bin/id
传递-n
到id
将显示名称而不是 ID 号,-u
显示用户(而不是组等其他信息),并-r
导致显示真实用户 ID。如果没有-r
,-u
则显示有效用户 ID。此行为完全适用于复制我id
刚刚做的。
当我以替代用户身份运行它时,实际用户 ID 和有效用户 ID 都会更改。这是su
和sudo
编写方式的一部分,并不是因为su
它本身是 setuid root,尽管它是。(这就是为什么我使用典型的 setuid 可执行文件而不是或passwd
作为示例。)这是我们的基准,以查看当前目录中的是否按预期工作:su
sudo
id
$ ./id -nu # ek runs id, displaying the effective user
ek
$ ./id -nur # ek runs id, displaying the real user
ek
$ su ek2 -c './id -nu' # ek2 runs id, displaying the effective user
Password:
ek2
$ su ek2 -c './id -nur' # ek2 runs id, displaying the real user
Password:
ek2
现在我制作这个id
setuid 的本地副本:
$ chmod u+s id
$ ls -l id
-rwsr-xr-x 1 ek ek 39760 Oct 5 11:42 id
现在当我运行它时,它的真实用户 ID 仍然是运行它的用户的 ID,而它的有效用户 IDek
即使在ek2
运行它时也是:
$ ./id -nu # ek runs id, displaying the effective user
ek
$ ./id -nur # ek runs id, displaying the real user
ek
$ su ek2 -c './id -nu' # ek2 runs id, displaying the effective user
Password:
ek
$ su ek2 -c './id -nur' # ek2 runs id, displaying the real user
Password:
ek2
现在我从所有者那里拿走可执行权限,但将其留给其他所有人:
$ chmod u-x id
$ ls -l id
-rwSr-xr-x 1 ek ek 39760 Oct 5 11:42 id
ek2
ek
尽管ek
无法运行它,但仍可以使用 的有效用户 ID 来运行它:
$ ./id -nu # ek runs id, displaying the effective user
-bash: ./id: Permission denied
$ ./id -nur # ek runs id, displaying the real user
-bash: ./id: Permission denied
$ su ek2 -c './id -nu' # ek2 runs id, displaying the effective user
Password:
ek
$ su ek2 -c './id -nur' # ek2 runs id, displaying the real user
Password:
ek2
ek
但是,如图所示,这并没有产生与实际运行相同的结果。如果被允许运行该程序,ek2
那么实际上无法做到,除非程序允许。ek
ek
(之后,我运行rm id
删除该文件,这样我的主目录中就不会有不必要的 setuid 可执行文件。或者你也可以用 取消设置 setuid 位chmod -s id
。)
答案3
s
这确实是正确的。通常情况下,当x
在相关文件上设置时,应该是。但是,当x
执行位已被删除时,则更s
改为,以S
通知您尽管该文件使用了 setuid,但尚未x
设置。
x
在这种情况下,由于未设置,因此甚至不会执行。现在我们有了这个-r-Srwxr-x
,这意味着o
——其他人仍然可以执行此脚本。因此,当您更改为任何其他用户时,owner
脚本将运行
Info ls
:
‘s’
If the set-user-ID or set-group-ID bit and the corresponding
executable bit are both set.
‘S’
If the set-user-ID or set-group-ID bit is set but the
corresponding executable bit is not set.