在day5,中介绍了一些常见的文件权限位,其实除了这些 rwx 权限位之外,在Linux中,还有一种特殊的权限 s 位。
SUID
我们称有该权限位的可执行文件为具有SUID 特殊权限的可执行文件,所具有的功能是,只要用户对设有 SUID 的文件有执行权限,那么当用户执行此文件时,会以文件所有者的身份去执行此文件,一旦文件执行结束,身份的切换也随之消失。
我们先看一个文件:
afei@ubuntu:~$ ls -al /etc/shadow
-rw-r----- 1 root shadow 1652 Oct 11 06:02 /etc/shadow
文件只有 root 用户有写入权限
afei@ubuntu:~$
用户在使用 passwd 命令修改密码时,其实用就是对 /etc/shadow 这个文件进行修改,那么为什么普通用户可以修改这个文件呢?这就是 s 权限位的作用,当一个可执行文件带有 s 权限位的时候,用户执行它的时候,会临时获得文件所有者 root 的权限,就可以修改只有root用户才能修改的文件。
我们查看一下 passwd 命令的权限位。
afei@ubuntu:~$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 Jul 14 15:08 /usr/bin/passwd
原本属主的可执行权限位 x 变成了 s
afei@ubuntu:~$
passwd 命令的属主可执行权限位 s 可以看成是一把尚方宝剑,在有了这个权限位之后,用户在执行它的时候,就可以对只有 root 用户才能修改的文件进行修改。
我们来做一个尝试:
afei@ubuntu:~$
afei@ubuntu:~$ su root
Password:
切换到root用户
root@ubuntu:/home/afei#
root@ubuntu:/home/afei# ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 Jul 14 15:08 /usr/bin/passwd
原本的 passwd 命令原有 s 权限位
root@ubuntu:/home/afei#
root@ubuntu:/home/afei# chmod u-s /usr/bin/passwd
去除 passwd 命令原有的 s 权限位
root@ubuntu:/home/afei#
root@ubuntu:/home/afei# ls -l /usr/bin/passwd
-rwxr-xr-x 1 root root 68208 Jul 14 15:08 /usr/bin/passwd
passwd 命令不再有 s 权限位
root@ubuntu:/home/afei#
root@ubuntu:/home/afei# su afei
afei@ubuntu:~$
afei@ubuntu:~$ passwd afei
Changing password for afei.
Current password:
New password:
Retype new password:
passwd: Authentication token manipulation error
提示身份验证出错
passwd: password unchanged
afei@ubuntu:~$
afei@ubuntu:~$ su root
Password:
root@ubuntu:/home/afei#
root@ubuntu:/home/afei# chmod u+s /usr/bin/passwd
重新添加 passwd 命令 s 权限位
root@ubuntu:/home/afei#
root@ubuntu:/home/afei# ls -l !$
ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 Jul 14 15:08 /usr/bin/passwd
root@ubuntu:/home/afei#
root@ubuntu:/home/afei# su afei
afei@ubuntu:~$ passwd afei
Changing password for afei.
Current password:
New password:
Retype new password:
passwd: password updated successfully
重新添加 passwd 命令 s 权限位,修改密码成功
afei@ubuntu:~$
afei@ubuntu:~$
SGID
(此部分引用自《liinux就该这么学》)
SGID特殊权限有两种应用场景:
当对可执行二进制文件进行设置时,能够让执行者临时获取文件所属组的权限;
当对目录进行设置时,则是让目录内新创建的文件自动继承该目录原有用户组的名称。
SGID的第一种功能是参考SUID而设计的,不同点在于执行程序的用户获取的不再是文件所有者的临时权限,而是获取到文件所属组的权限。举例来说,在早期的Linux系统中,/dev/kmem是一个字符设备文件,用于存储内核程序要访问的数据,权限为:
cr--r----- 1 root system 2, 1 Feb 11 2017 kmem
除了root管理员或属于system组的成员外,所有用户都没有读取该文件的权限。由于在平时需要查看系统的进程状态,为了能够获取进程的状态信息,可在用于查看系统进程状态的ps命令文件上增加SGID特殊权限位。下面查看ps命令文件的属性信息:
-r-xr-sr-x 1 bin system 59346 Feb 11 2017 ps
这样一来,由于ps命令被增加了SGID特殊权限位,所以当用户执行该命令时,也就临时获取到了system用户组的权限,从而顺利地读取到了设备文件。
前文提到,每个文件都有其归属的所有者和所属组,当创建或传送一个文件后,这个文件就会自动归属于执行这个操作的用户(即该用户是文件的所有者)。如果现在需要在一个部门内设置共享目录,让部门内的所有人员都能够读取目录中的内容,那么就可以在创建部门共享目录后,在该目录上设置SGID特殊权限位。这样,部门内的任何人员在里面创建的任何文件都会归属于该目录的所属组,而不再是自己的基本用户组。此时,用到的就是SGID的第二个功能,即在某个目录中创建的文件自动继承该目录的用户组(只可以对目录进行设置)。
[root@linuxprobe ~]# cd /tmp
[root@linuxprobe tmp]# mkdir testdir
[root@linuxprobe tmp]# ls -ald testdir
drwxr-xr-x. 2 root root 6 Oct 27 23:44 testdir
[root@linuxprobe tmp]# chmod -R 777 testdir
[root@linuxprobe tmp]# chmod -R g+s testdir
[root@linuxprobe tmp]# ls -ald testdir
drwxrwsrwx. 2 root root 6 Oct 27 23:44 testdir
在使用上述命令设置好目录的777权限(确保普通用户可以向其中写入文件),并为该目录设置了SGID特殊权限位后,就可以切换至一个普通用户,然后尝试在该目录中创建文件,并查看新创建的文件是否会继承新创建的文件所在的目录的所属组名称:
[root@linuxprobe tmp]# su - linuxprobe
[linuxprobe@linuxprobe ~]$ cd /tmp/testdir
[linuxprobe@linuxprobe testdir]$ echo "linuxprobe.com" > test
[linuxprobe@linuxprobe testdir]$ ls -al test
-rw-rw-r--. 1 linuxprobe root 15 Oct 27 23:47 test
以上介绍内容,缺乏实践性,可做如下案例补充:
假设我们需要共享一个目录 sharedir 给同一用户组 share 下的其他用户,并确保所有用户在该目录下创建的文件,互相都可以访问:
首先我们需要创建一个新的目录和一个新的用户组,并将需要共享的用户添加到该用户组里面:
afei@ubuntu:~/myWorkSpace$ mkdir sharedir
创建用于共享的文件夹
afei@ubuntu:~/myWorkSpace$ sudo groupadd share
添加新的用户组
afei@ubuntu:~/myWorkSpace$
afei@ubuntu:~/myWorkSpace$ sudo chown afei:share -R sharedir
设置文件夹的属组为 share
afei@ubuntu:~/myWorkSpace$ sudo usermod -aG share afei
afei@ubuntu:~/myWorkSpace$ sudo usermod -aG share afei-login
将 afei 和 afei-login 两个用户添加到 share 组中
afei@ubuntu:~/myWorkSpace$ ls -l
total 4
drwxrwxr-x 2 afei share 4096 Oct 14 07:59 sharedir
现在afei 和 afei-login 用户对 sharedir 目录已经有了 “r w x” 权限
当我们做到者的时候,你觉得是不是达到该目录下的文件的目的了呢?
的确,现在 afei 和 afei-login 都可以在 sharedir 目录下创建文件了,但是由于不同的用户创建的文件,默认的属组还是创建文件的用户的属组,所以其实 afei 创建的文件 afei-login 用户是编辑不了的,同理 afei-login 创建的文件 afei 用户是编辑不了的。
afei@ubuntu:~/myWorkSpace/sharedir$ touch afeiFile.text
afei@ubuntu:~/myWorkSpace/sharedir$ su afei-login
Password:
afei-login@ubuntu:/home/afei/myWorkSpace/sharedir$ echo aaaaa >> afeiFile.text
bash: afeiFile.text: Permission denied
切换到 afei-login 用户,不能编辑 afei 用户创建的文件
afei-login@ubuntu:/home/afei/myWorkSpace/sharedir$
afei-login@ubuntu:/home/afei/myWorkSpace/sharedir$
afei-login@ubuntu:/home/afei/myWorkSpace/sharedir$ touch afei-loginFile.text
afei-login@ubuntu:/home/afei/myWorkSpace/sharedir$
afei-login@ubuntu:/home/afei/myWorkSpace/sharedir$ exit
exit
afei@ubuntu:~/myWorkSpace/sharedir$ echo aaaa >> afei-loginFile.text
bash: afei-loginFile.text: Permission denied
切换到 afei 用户,不能编辑 afei-login 创建的文件
afei@ubuntu:~/myWorkSpace/sharedir$
原因就在于:
afei@ubuntu:~/myWorkSpace/sharedir$ ls -l
total 0
-rw-rw-r-- 1 afei afei 0 Oct 14 09:03 afeiFile.text
-rw-rw-r-- 1 afei-login afei-login 0 Oct 14 09:04 afei-loginFile.text
以上两个文件的属组还是创建它的用户的属组
afei@ubuntu:~/myWorkSpace/sharedir$
解决办法:
afei@ubuntu:~/myWorkSpace$ sudo chmod g+s sharedir
[sudo] password for afei:
afei@ubuntu:~/myWorkSpace$
afei@ubuntu:~/myWorkSpace$ ls -l
total 4
drwxrwsr-x 2 afei share 4096 Oct 14 09:04 sharedir
为 sharedir 添加了GUID权限
afei@ubuntu:~/myWorkSpace$ cd share
afei@ubuntu:~/myWorkSpace/sharedir$ touch afeiFile+s.text
afei@ubuntu:~/myWorkSpace/sharedir$ su afei-login
Password:
afei-login@ubuntu:/home/afei/myWorkSpace/sharedir$ echo aaaaa >> afeiFile+s.text
afei-login 用户对 afei 用户创建的文件修改成功
afei-login@ubuntu:/home/afei/myWorkSpace/sharedir$ exit
exit
afei@ubuntu:~/myWorkSpace/sharedir$ ls -l
total 4
-rw-rw-r-- 1 afei share 6 Oct 14 09:13 afeiFile+s.text
原因在于对为 sharedir 添加了GUID权限,之后,在其内部创建的文件,自动继承了 sharedir 的属组信息
-rw-rw-r-- 1 afei afei 0 Oct 14 09:03 afeiFile.text
-rw-rw-r-- 1 afei-login share 0 Oct 14 09:14 afei-loginFile+s.text
-rw-rw-r-- 1 afei-login afei-login 0 Oct 14 09:04 afei-loginFile.text
afei@ubuntu:~/myWorkSpace/sharedir$
|