Linux 中SUID、SGID和SBIT的用途

Linux中,用户的权限一般会根据用户的uid和gid来确定,但是在运行的时候,系统根据的是用户的有效uid和有效gid,本来的话,在执行文件前,用户的uid和gid是也就是用户的有效uid和有效gid,这也就决定了用户的权限,但是,当文档设置了suid和sgid后,用户的有效uid和gid将会改变,这也就是suid和sgid的功能。

其实在UNIX的实现中,文件权限用12个二进制位表示,如果该位置上的值是1,表示有相应的权限:

1
2
3
11 10 9 8 7 6 5 4 3 2 1 0

S G T r w x r w x r w x

第11位为SUID位,第10位为SGID位,第9位为sticky位,第8-0位对应于上面的三组rwx位。

给文件加SUID和SUID的命令如下:

1
2
3
4
5
6
7
chmod u+s filename 设置SUID位

chmod u-s filename 去掉SUID设置

chmod g+s filename 设置SGID位

chmod g-s filename 去掉SGID设置

另外一种方法是chmod命令用八进制表示方法的设置。如果明白了前面的12位权限表示法也很简单。如 chmod 2770 filename,将filename文件设置权限为rwxrws---,此时的sgid位有效,如果为chmod 2760 filename, 将filename文件设置权限为rwxrwS---,此时sgid无效。

suid只对可执行文件有意义,sgid只对目录和可执行文件有意义。suid和sgid起作用的前提是,调用者对文件有执行权限,对目录有写以及执行权限,否则的话,即使设置了suid和sgid位,都会无效。

由于SUID和SGID是在执行程序(程序的可执行位被设置)时起作用,而可执行位只对普通文件和目录文件有意义,所以设置其他种类文件的SUID和SGID位是没有多大意义的。

当可执行文件设置了suid后,调用者在运行该文件的时候(前提是调用者有运行该文件的权限),将会暂时获得该文件拥有者的权限,此时调用者的有效uid就是文件拥有者的uid,例如,使用如下命令:

1
ls -l /usr/bin/passwd

我们会得到如下的结果:

1
-rwsr-xr-x 1 root root 42824 Sep 13  2012 /usr/bin/passwd

可以看到,在文件拥有者的执行位上出现为s而不是x,所以说passwd这个程序是具有SUID权限的。我们知道在修改用户密码的时候,用的就是passwd这个命令,而我们又知道在linux下面,用户密码是存储在/etc/shadow这个文件里面的。首先查看一下/etc/shadow这个文件的权限:

1
ls -l /etc/shadow

返回的结果如下:

1
-rw-r----- 1 root shadow 1138 Dec 13 20:00 /etc/shadow

由上面的结果,我们知道只有root可以往shadow文件中写入数据,其他用户连查看的权限都没有。那我们平时是怎么修改密码呢?没错,就是和SUID有关。当我们使用passwd命令时,就获得了passwd的所有者即root的权限,进而可以对shadow文件进行写入操作。

SGID即Set GID的缩写,它出现在文件所属组权限的执行位上面,它对普通二进制文件和目录都有效。当它作用于普通文件时,和SUID类似,在执行该文件时,用户将获得该文件所属组的权限。当SGID作用于目录时,意义就非常重大了。当用户对某一目录有写和执行权限时,该用户就可以在该目录下建立文件,如果该目录用SGID修饰,则该用户在这个目录下建立的文件都是属于这个目录所属的组。

SBIT即Sticky Bit,它出现在其他用户权限的执行位上,它只能用来修饰一个目录。当某一个目录拥有SBIT权限时,则任何一个能够在这个目录下建立文件的用户,该用户在这个目录下所建立的文件,只有该用户自己和root可以删除,其他用户均不可以。例如:

1
ls -ld /tmp

可以得到以下结果:

1
drwxrwxrwt 12 root root 12288 Dec 17 16:33 /tmp