可执行权限模式S用于什么?
如果为具有执行权限的文件权限添加setuid位,则会将x
更改为s
,表示如果执行该文件,它将作为文件的所有者而不是实际执行该文件的人执行。
但我也注意到,如果您添加s
权限但删除了x
权限,则会更改为权限列表中的S
不知何故,这意味着它无法执行,但如果可以执行,它将同时作为所有者执行? 是对的吗?
我误解了这个许可吗? 它是干什么用的? 这是什么意思?
所有四种组合都存在且有意义。
“这个文件的实际所有者可以运行吗?” 和“系统假装谁将运行此文件?” 是两个单独的问题。 所有四种组合都是可能且有意义的。
ls -l
或stat -c %A
显示的权限字符串显示在所有者执行位置(即代替?
in ---?------
),四个不同的字符,每个组合一个:
-
-
表示所有者无法运行该文件,如果非所有者运行该文件,则它将以其他用户身份运行。 -
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
格式说明符而不是%A
。 为简化起见,我取消了所有其他模式位。
$ touch abcd $ 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' abcd ---------- a ---x------ b ---S------ c ---s------ d $ stat -c '%04a %n' abcd 0000 a 0100 b 4000 c 4100 d
这清楚了……如果你对八进制感到满意的话。 如果你想用二进制看它(它们毕竟是 位 )你可以转换表示:
$ stat -c '%a %n' abcd | perl -pe 's/\d+/sprintf("%012b", oct($&))/e' 000000000000 a 000001000000 b 100000000000 c 100001000000 d
Setuid设置有效用户ID,而不是真实用户ID。
执行位控制是否可以成功运行文件 ,而setuid / setgid位控制新进程在允许创建时运行的身份。 因此, S
表示的权限组合( -x,+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
有rx
。 由于x
,即使不是root用户或root用户组的用户也可以运行passwd
。 对于老板来说 ,它的开头就近了。 由于s
,程序以root身份运行,即使非所有者运行它也是如此。 但是当你自己运行passwd
,它会重置密码,而不是root密码。
passwd
能够对用户和密码数据库执行任何更改,因为它使用root的有效用户ID运行。 但它旨在拒绝更改任何人的密码,但用户运行它 – 除非该用户是root用户 – 因为它检查其真实用户ID。
这是setuid可执行文件的典型用例:创建一个接口,允许一个用户以有限的方式使操作作为另一个用户执行,并由setuid可执行文件的代码检查。 因此,只有在设计具有这些权限的程序上设置setuid位(或setgid位)才是安全的。
这是理解权限S
表示为什么不是谜的另一个难题:即使允许程序运行,setuid位赋予的function也不会像实际运行程序那样实现与其所有者相同的function。 。
使用id
副本检查UID和EUID会显示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都会被更改。 这是su
和sudo
如何编写的一部分,并不仅仅是su
本身是setuid root的结果,尽管它是。 (这就是为什么我使用passwd
作为典型setuid可执行文件的一个例子,而不是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,而它的有效用户ID是ek
即使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 ux id $ ls -l id -rwSr-xr-x 1 ek ek 39760 Oct 5 11:42 id
ek2
仍然可以像ek
的有效用户ID一样运行它,即使ek
无法运行它:
$ ./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
实际运行它相同的结果。 如果ek
被允许运行程序, ek2
无法真正做到ek
可以做的事情,除非程序允许它。
(之后,我运行rm id
删除文件,所以我的主目录中没有不必要的setuid可执行文件。或者你可以用chmod -s id
取消setuid位。)
如果设置了setuid,则输出显示S
,但用户权限不包括execute。 但是,只要group或other可以执行,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
这确实是对的。 通常情况下,当x
在相关文件上设置时应该是s
。 但是,如果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.