SUID、SGID和Sticky Bits是非常强大的特殊权限,在linux系统中,你可以把它们设在 在目录和可执行文件里面。本文将讨论它们在使用时的好处和一些可能存在的“坑”
对于一个多用户操作系统来说,要保证在多用户的状态下的安全是一件不容易的事情。就拿密码来说,它必须保存在系统里面,当用户登录的时候,他们输完密码,系统就会自动对比,所以对于系统来说,密码就是进入的钥匙,因此必须保证这些密码的安全。
在linux里,这些存储在系统里的密码通过两种方式来包含:第一,它们必须被加密;第二,只有拥有root权限的人才能访问保存密码的文件。这样看起来是挺完美的,但却有一个问题:如果只有拥有root权限的人才能够访问密码文件,那么那些没有root权限的人怎么办呢?就拿登录来说,如果他们不能访问密码文件,那么怎么的登录系统,怎么修改自己的密码呢?如果只能root用户来修改,那root用户岂不是要忙死了?
一般来说,当一个用户运行命令或者程序的时候,那么这个命令或者程序所使用的的用户身份就是调用这它的人身份,因此这个命令或者程序所有用的权限跟这个用户是一样的。比如,当root用户运行passwd来更改密码的时候,那么它调用的就是root的权限。这样,passwd就可以随意的访问/etc/shadow这个文件了。
如果要是一般用户也可以修改他们自己的密码,那能否这样做:当普通用户运行passwd命令时,临时提升他们的权限,变成root的权限,这样他们就可以修改自己的密码了。这样挺起啊是不是很爽?实际上,linux系统也是这么干的。
linux系统通过SUID(set user id bit)来达到上述目的的。一旦设置了这个权限,那么运行命令或者程序时,所获得的权限是文件拥有者的权限,而不是运行这个命令或者程序的用户的权限。其实,通过英文的字面意思就可以理解:设置用户id位。
以上方案听起来不错,但会存在一个问题,如果用户在运行passwd时候会临时拥有root权限,那么他是否就可以更改别人的密码了呢?要解决这问题,需要在passwd这个程序实现用户验证的功能,而不是在操作系统层面来做。
在passwd源码里,以下代码就是来验证root用户的:
......
/*
* The program behaves differently when executed by root than when
* executed by a normal user.
*/
amroot = (getuid () == 0);
......
/*
* Root can change any password any time.
*/
if (amroot) {
return;
}
......
所以,当系统把决定权交给程序本身时,使用SUID这个权限就要很小心。这个对于开源软件来说还好,大家可以看源码,找问题,一般不容易出现安全问题。但是如果是一些来历不明的软件,那就要非常小心了,除非你知道这个软件的相关背景,否则最好不要配置这个权限,以防这个程序给系统带来安全风险,从而导致系统被入侵,丢失了重要数据。(未完待续)
书接上回,在linux系统里,有许多命令时代SUID权限的,以下这些是常见的:
$ ls -l /bin/su /bin/mount /bin/umount /usr/bin/passwd
-rwsr-xr-x 1 root root 55528 2月 7 2022 /bin/mount
-rwsr-xr-x 1 root root 67816 2月 7 2022 /bin/su
-rwsr-xr-x 1 root root 39144 2月 7 2022 /bin/umount
-rwsr-xr-x 1 root root 68208 3月 14 2022 /usr/bin/passwd
可以看到在每个命令拥有者权限那里的x变成了s:
-rwsr-xr-x 1 root root 55528 2月 7 2022 /bin/mount
一旦这个位置出现s,那就表示这个程序时被赋予了SUID权限。我们知道,每个文件在拥有者这里有三个权限,分别是rwx,表示读、写、执行,如果这个位置出现了字母,那么就表示有这个权限,否则就是“-”号,表示没有这个权限。当程序没有被赋予x权限却被赋予了SUID,那么这里就会变成大写的“S”表示这个权限是空的,也就是说用户不能执行这个程序,自然就无法提升为root权限了。
ok,来看看例子,看看这个SUID是不是按照我们预期的执行的。
我这里有个用户jack,当他修改密码时会出现以下提示:
[jack@VM-0-14-centos root]$ passwd
Changing password for user jack.
Changing password for jack.
(current) UNIX password:
打开另外一个终端观察:
[root@VM-0-14-centos ~]# ps -ef |grep passwd
root 25196 25170 0 17:56 pts/2 00:00:00 passwd
root 25298 25205 0 17:56 pts/3 00:00:00 grep passwd
可以看到这里调用passwd的用户变成了root。