setuid 和 setgid 分别是 set uid ID upon execution 和 set group ID upon execution 的缩写。我们一般会再次把它们缩写为 suid 和 sgid。它们是控制文件访问的权限标志(flag),它们分别允许用户以可执行文件的 owner 或 owner group 的权限运行可执行文件。

说明:本文的演示环境为centos7.4。


SUID

在 Linux 中,所有账号的密码记录在 /etc/shadow 这个文件中,并且只有 root 可以读写入这个文件:

ls - l /etc/shadow
---------- 1 root root 946 May 13 11:37 /etc/shadow

如果另一个普通账号 test1 需要修改自己的密码,就要访问 /etc/shadow 这个文件。但是明明只有 root 才能访问 /etc/shadow 这个文件,这究竟是如何做到的呢?事实上,test1 用户是可以修改 /etc/shadow 这个文件内的密码的,就是通过 SUID 的功能。让我们看看 passwd 程序文件的权限信息:

ls -l /usr/bin/passwd
-rwsr-xr-x. 1 root root 27832 Jun 10  2014 /usr/bin/passwd

上述命令,owner 的信息为 rws 而不是 rwx。当s 出现在文件拥有者的x 权限上时,就被称为设置了SUID,其特点如下:

  • SUID 权限仅对二进制可执行文件有效
  • 如果执行者对于该二进制可执行文件具有 x 的权限,执行者将具有该文件的所有者的权限
  • 本权限仅在执行该二进制可执行文件的过程中有效

下面我们来看 test1 用户是如何利用 SUID 权限完成密码修改的:

  1. test1 用户对于 /usr/bin/passwd 这个程序具有执行权限,因此可以执行 passwd 命令
  2. passwd 命令的所有者为 root
  3. test1用户执行 passwd程序(命令)的过程中会暂时获得 root 权限
  4. 因此 test1 用户在执行passwd 程序(命令)的过程中可以修改 /etc/shadow文件

但是如果由 test1 用户执行 cat 命令去读取 /etc/shadow 文件是不行的:

原因很清楚,test1 用户没有读 /etc/shadow 文件的权限,同时 cat 命令也没有被设置 SUID

如果想让任意用户通过cat 命令读取 /etc/shadow 文件的内容也是非常容易的,给它设置 SUID 权限就可以了:

chmod 4755 /bin/cat

现在 cat 已经具有了 SUID 权限,已经可以 cat 到 /etc/shadow 的内容了。但是这样非常不安全,所以赶快通过

下面的命令把 cat 的 SUID 权限移除掉:

chmod 755 /bin/cat

SGID

s标志出现在用户组x权限时称为 SGID。SGID 的特点与 SUID 相同,我们通过 /usr/bin/locate 程序来演示其用法。locate 命令通过查询数据库文件 /var/lib/mlocate/mlocate.db 实现快速的文件查找

locate 程序的权限如下图所示:

ls -l /usr/bin/locate
-rwx--s--x. 1 root slocate 40496 Jun 10  2014 /usr/bin/locate

上述命令可以看作在用户组位置出现了 s,也就是说被设置了 SGID权限。

普通用户 test1 执行 locate 命令时,test1 就会获得用户组 locate 的执行权限,又由于用户组对 mlocate.db 具有读权限,所以 test1 就可以读取 mlocate.db 了。

二进制程序外,SGID 也可以用在目录上。当一个目录设置了 SGID 权限后,它具有如下功能:

  1. 用户若对此目录具有 r 和 x 权限,该用户能够进入该目录
  2. 用户在此目录下的有效用户组将变成该目录的用户组
  3. 若用户在此目录下拥有 w 权限,则用户所创建的新文件的用户组与该目录的用户组相同

下面看个例子,当前登录用户为test1,创建 testdir 目录:

ls -l testdir
drwxrwxr-x. 1 test1 test1 27832 Jun 10  2014 ./testdir

我们将testdir的所属组改为test2,我们在此目录下创建一个文件 testfile ,此时testfile的拥有者和所属组都是test1

ls -l testdir
drwxrwsr-x 2 test1 test2 4096 5月  13 14:03 testdir
-rw-rw-r-- 1 test1 test1     0 5月  13 12:17 testfile

#testfile 的所有者 和所属组都是test1

此时,我们开始设置 SGID 权限了:

sudo chmod 2775 testdir

我们在testdir目录下再创建一个testfile2文件,然后查看其权限:

-rw-rw-r-- 1 test1 test1  0 5月  13 14:01 testfile1
-rw-rw-r-- 1 test1 test2 0 5月  13 14:03  testfile2

我们看到新建的testfile2 的所属组为 test2 ,可见被设置了SGID权限之后的目录,在该目录下创建的文件所属组都是该文件夹的所属组。

总结:当 SGID 作用于普通文件时,和 SUID 类似,在执行该文件时,用户将获得该文件所属组的权限。当 SGID 作用于目录时,意义就非常重大了。当用户对某一目录有写和执行权限时,该用户就可以在该目录下建立文件,如果该目录用 SGID 修饰,则该用户在这个目录下建立的文件都是属于这个目录所属的组。

SBIT

SBIT 是 the restricted deletion flag or sticky bit 的简称。SBIT 目前只对目录有效,用来阻止非文件的所有者删除文件。比较常见的例子就是 /tmp 目录:

权限信息中最后一位t表明该目录被设置了 SBIT 权限。SBIT 对目录的作用是:当用户在该目录下创建新文件或目录时,仅有自己和 root 才有权力删除。

查看tmp目录的权限:

drwxrwxrwt.   8 root root 2314240 May 13 14:18 tmp

设置 SUID、SGID、SBIT 权限

以数字的方式设置权限:

SUID对应数组4SGID对应数字 2SBIT 对应数字 1

所以如果要为一个文件权限为 “-rwxr-xr-x” 的文件设置 SUID 权限,需要在原先的 755 前面加上 4,也就是 4755:

chmod 4755 filename

同样,可以用 21 来设置 SGID 和 SBIT 权限。设置完成后分别会用 s, s, t 代替文件权限中的 x

可以三个权限一起设置,也就是说权限位上同时出现st,如果文件本身没有x权限,对应位上的s或者t将变为大写。

例子:

chmod 666 filename
-rw-rw-rw- 1 root root      0 May 13 14:32 test2

执行 chmod 7666 filename,因为 666 表示 “-rw-rw-rw”,均没有 x 权限,查看效果:

-rwSrwSrwT 1 root root      0 May 13 14:32 test2

上述权限位上均变为大写。

通过符号类型改变权限:

chmod u+s testfile # 为 testfile 文件加上 SUID 权限。
chmod g+s testdir  # 为 testdir 目录加上 SGID 权限。
chmod o+t testdir  # 为 testdir 目录加上 SBIT 权限。

SUID、SGID、SBIT 权限都是为了实现特殊功能而设计的,其目的是弥补 ugo 权限无法实现的一些使用场景。但是这些权限一定一定要慎用,一旦用错将会是非常危险的。


Leave Your Comment

电子邮件地址不会被公开。 必填项已用*标注