linux文件特殊权限SUID,SGID,SBIT。 我们前面已经多次通过ls -al命令查看文件的详细信息了,也知道文件的rwx读写执行权限。 但是如果你通过ls命令查看/tmp或者/usr/bin/passwd文件的详细信息,会发现文件类型与权限字段有些不太一样:

              peter@initroot:~$ ls -ld /tmp
              drwxrwxrwt 18 root root 200704 Jan  6 21:51 /tmp
              peter@initroot:~$ ls -al /usr/bin/passwd
              -rwsr-xr-x 1 root root 59640 Mar 23  2019 /usr/bin/passwd
            
除了rwx这几个权限属性外,竟然还有s和t,这两个称为特殊权限属性。特殊权限属性与linux进程和系统账号密切相关。 等到讲解linux进程的时候我们还会讲解这方面的内容, 关于linux进程参考: linux程序与进程

1.设置用户ID(Set UID)

回到顶部

当s属性出现在文件拥有者的x权限位置时,就成为设置用户ID,Set UID,简称为SUID。例如上面的/usr/bin/passwd文件的权限:-rwsr-xr-x。
一个文件的SUID功能描述如下:
1.SUID权限仅对二进制可执行程序文件(binary program)有效;
2.执行者对于该文件需要具有x的可执行权限;
3.本权限仅在执行该文件的过程中有效(run-time);
4.执行者将具有该程序文件拥有者(owner)的权限(执行进程的有效用户将变为该文件的拥有者)
我们以为passwd命令为例说明。我们在讲解用户账号的时候说过,passwd命令实际上会修改/etc/shadow这个文件。
我们用ls命令查看该文件想的权限:

              peter@initroot:/tmp$ ls -al /etc/shadow
              -rw-r----- 1 root shadow 1365 Jul 28 15:09 /etc/shadow
            
通过输出我们发现,只有root用户才有权限修改/etc/shadow文件。而普通账号peter却可以通过passwd命令修改自己的口令密码。 这好像有点说不通啊,普通用户peter可以通过passwd命令修改/etc/shadow文件,但是/etc/shadow文件的权限属性显示只有root用户才有权限修改该文件。 这就是passwd命令文件的特殊权限SUID的作用了。
我们对照/usr/bin/passwd文件的权限-rwsr-xr-x说明:
1. peter对于/usr/bin/passwd文件来说是other用户,具有可执行权限x,表示peter可以执行passwd命令;
2. peter执行passwd命令的过程中,会暂时获得passwd命令文件拥有者的权限,passwd命令文件的拥有者是root,所以peter临时获得了root的权限,火鸡变凤凰,青铜一跃变身王者;
3. 有了root权限的加持,/etc/shadow文件就可以被peter所执行的passwd命令修改了。
如果peter用cat命令读取/etc/shadow文件的内容,由于cat命令文件没有设置SUID,所有peter也就无法通过cat读取/etc/shadow文件了:
              peter@initroot:/tmp$ cat /etc/shadow
              cat: /etc/shadow: Permission denied
              peter@initroot:/tmp$ whereis cat
              cat: /bin/cat /usr/share/man/man1/cat.1.gz
              peter@initroot:/tmp$ ls -l /bin/cat
              -rwxr-xr-x 1 root root 35064 Jan 18  2018 /bin/cat
            
以上我们先通过cat读取/etc/shadow文件的内容,cat命令提示Permission denied。表示没有权限执行。 通过whereis命令找到cat命令对应的可执行程序文件为/bin/cat,最后通过ls -l命令查看/bin/cat文件的详细信息。
需要注意的是,SUID仅对二进制可执行程序(binary program)文件有效,对shell script脚本文件是没有意义的。 因为shell脚本文件都是由linux命令组成的,最终还是需要看命令文件是够设置SUID。另外,SUID对目录文件也是没有意义的。 只需要记住一句SUID仅适用于二进制可执行程序(binary program)文件。

2.设置用户组ID(Set GID)

回到顶部

和SUID类似,当s属性出现在文件拥有者可执行权限x的位置时称为SUID,那么当s位于文件所属用户群组的可执行权限x的位置时则称为Set GID,简称SGID。 locate命令是SGID的典型代表。在linux mint下,我们通过whereis和ls命令找到locate命令对应的二进制可执行文件:

              peter@initroot:/tmp$ whereis locate
              locate: /usr/bin/locate /usr/share/man/man1/locate.1.gz
              peter@initroot:/tmp$ ls -l /usr/bin/locate
              lrwxrwxrwx 1 root root 24 Jul 10 20:09 /usr/bin/locate -> /etc/alternatives/locate
              peter@initroot:/tmp$ ls -l /etc/alternatives/locate
              lrwxrwxrwx 1 root root 16 Jul 10 20:09 /etc/alternatives/locate -> /usr/bin/mlocate
              peter@initroot:/tmp$ ls -l /usr/bin/mlocate
              -rwxr-sr-x 1 root mlocate 43088 Mar  2  2018 /usr/bin/mlocate
            
这个命令隐藏的太深了,我们通过好几个ls命令才找到locate的真正可执行文件为/usr/bin/mlocate,该文件的权限属性为-rwxr-sr-x。 与SUID不同的是, SGID可以针对文件或目录来设置!针对文件,SGID与SUID类似,功能如下:
1.SGID对二进制程序文件有用;
2.执行者对于该文件需要具有x的可执行权限;
3.执行者在执行的过程中将会获得该程序文件所属用户群组的权限!
我们以locate命令说明,通过上面可知locate命令对应的可执行程序文件为/usr/bin/mlocate,locate命令会搜寻/var/lib/mlocate/mlocate.db这个文件的内容, 我们通过ls命令观察这两个文件:
              peter@initroot:/tmp$ ls -l /usr/bin/mlocate
              -rwxr-sr-x 1 root mlocate 43088 Mar  2  2018 /usr/bin/mlocate
              peter@initroot:/tmp$ ls -l /var/lib/mlocate/mlocate.db
              -rw-r----- 1 root mlocate 35086123 Jan  6 18:43 /var/lib/mlocate/mlocate.db
            
由上面输出可知,要想读取/var/lib/mlocate/mlocate.db文件的内容,需要具有root权限,或者用户组mlocate的权限, 而peter对该文件来说是other用户,没有任何权限。如果peter用户执行了locate命令,那么peter将会临时获得用户组mlocate的权限, 因此就可以读取/var/lib/mlocate/mlocate.db文件了。
除了可执行程序文件binary program外,SGID也可作用于目录,这也是非常常见的一种用途! 当一个目录设置了SGID权限后,将具有如下的功能:
1.如果用户对目录拥有r与x的权限,该用户能够进入此目录;
2.用户在此目录下的有效用户群组(effective group)将会变成该目录的用户群组;
3.若用户在此目录下具有w的权限(可以新建文件),且该用户建立了一个新文件,那么这个新文件的用户群组与此目录的用户群组相同。
SGID对于项目开发来说是非常重要的!因为这涉及用户群组权限的问题。

3.黏着位Sticky Bit

回到顶部

黏着位Sticky Bit, 简称SBIT。当t属性出现在目录其他用户other可执行权限x的位置时,表示该目录设置了黏着位。 SBIT只针对目录有效,对于文件已经没有效果了。SBIT对于目录的作用是:
当用户对于此目录具有w和x的权限,亦即具有写入的权限时;
当用户在该目录下建立文件或目录时,仅有自己与root才有权力删除该文件。
当用户是目录的用户群组或其他人身份,并且拥有该目录的w权限,那么这个用户就可以对该目录内任何人建立的目录或文件均可进行删除、更名、移动等动作。 这并不是我们希望看到的,我们不希望该用户可以随意更改别人创建的文件或者目录。只希望该用户只能对自己建立的文件或者目录进行删除、更名、移动等动作。 这时就可以将该目录设置黏着位,即SBIT权限。SBIT权限最常见的例子就是/tmp目录,我们通过ls命令查看/tmp目录的权限信息:

              peter@initroot:~$ ls -ld /tmp
              drwxrwxrwt 18 root root 200704 Jan  6 21:51 /tmp
            
/tmp目录的权限属性为drwxrwxrwt, 该权限表明,任何人都可以在/tmp目录内新增、修改文件,但仅有文件或者目录的建立者和root用户才有权限删除自己的创建的目录或文件。 这个特性也是非常重要的!可以按照如下步骤做个简单的测试:
1. 以超级用户root或者一般普通用户cristina登入系统,通过cd命令切换到/tmp目录中;
2. 通过touch命令创建一个新文件test,用chmod命令将test文件权限设置为777;
3. 以一般使用者peter登入,并用cd命令切换到/tmp目录;
4. 用rm命令删除test文件!
最后发现peter是无法删除test文件的。
SUID、SGID和SBIT这几个概念和linux进程息息相关,我们会在讲到linux进程的时候,再次讲解SUID、SGID和SBIT。 下面我们接着介绍这几个特殊权限的设置。

4.SUID、SGID和SBIT权限设置

回到顶部

我们在用chmod命令修改文件权限属性的时候,r、w、x用数字表示分别是4、2、1。 chmod命令同样也可以用数字的形式设置特殊权限位。SUID、SGID、SBIT用数字表示分别为4、2、1。
我们再用chmod设置特殊权限的时候,只需要在权限属性前面加上特殊权限即可。 例如将一个文件的权限设置为-rwsr-xr-x,s在文件拥有者可执行权限的位置,为SUID。 原来的权限为-rwxr-xr-x,对应的数值为755,只需要在755前面加上数字4即可:

              peter@initroot:~$ chmod 4755 testfile
              peter@initroot:~$ ls -l testfile
              -rwsr-xr-x 1 peter peter 200704 Jan  6 21:51 testfile
            
除了数字设置形式外,也可以通过字符设置形式,其中SUID为u+s,而SGID为g+s,SBIT则是o+t!
将testfile文件权限设置为-rws--x--x:
              [root@initroot tmp]# chmod u=rwxs,go=x testfile;
              [root@initroot tmp]# ls -l testfile
              -rws--x--x 1 root root 0 Jun 10 07:25 testfile
            
将testfile问价加上SGID与SBIT权限:
              [root@initroot tmp]# chmod g+s,o+t testfile;
              [root@initroot tmp]# ls -l testfile
              -rws--s--t 1 root root 0 Jun 10 07:25 testfile
            
注意SUID不能用在目录上,而SBIT不能用在文件上!下面是一些练习:
              #切换到cd目录
              [root@initroot ~]# cd /tmp
              #建立一个测试用空档
              [root@initroot tmp]# touch test
              #加入具有 SUID 的权限
              [root@initroot tmp]# chmod 4755 test; ls -l test
              -rwsr-xr-x 1 root root 0 Jun 16 02:53 test
              #加入具有 SUID/SGID 的权限
              [root@initroot tmp]# chmod 6755 test; ls -l test
              -rwsr-sr-x 1 root root 0 Jun 16 02:53 test
              #加入 SBIT 的功能!
              [root@initroot tmp]# chmod 1755 test; ls -l test
              -rwxr-xr-t 1 root root 0 Jun 16 02:53 test
              #具有空的 SUID/SGID 权限
              [root@initroot tmp]# chmod 7666 test; ls -l test
              -rwSrwSrwT 1 root root 0 Jun 16 02:53 test
            
最后一个例子怎么会出现大写的S和T呢?因为s和t都是放置在x权限位置的,前提是必须具备相应的x权限。 当设置权限为7666的时候!user,group和others都没有可执行权限x了,所以,s和t也就没有意义了。 这时候就用大写的S和T替代,表示空的或者假的或者虚的权限。假大空! SUID、SGID和SBIT权限的前提是需要具备相应的可执行权限。

initroot编辑整理,转载请注明www.initroot.com