三种特殊权限简介
在 Linux 下,除了rwx权限外,有时还会看到s和t这样的权限,这些是 Linux 下的特殊权限,包括SUID,SGID,SBIT。
本文内容主要参考鸟哥的文章 - Linux 文件与目录管理,更多内容可阅读鸟哥原文。
示例
注意原来的权限的x位置上的变化,x被s和t所替换了。
ls -ld /usr/bin/passwd /tmp /usr/bin/walldrwxrwxrwt 12 root root 4096 Jun 14 15:51 /tmp-rwsr-xr-x 1 root root 59640 Jan 25 15:09 /usr/bin/passwd-rwxr-sr-x 1 root tty 30800 May 16 10:41 /usr/bin/wall |
Linux 命令行中运行其实是有不同的高亮背景表示这些文件拥有特殊权限的。
SUID
当一个设置了 SUID 位的可执行文件被执行时,该文件将以所有者的身份运行,也就是说无论谁来执行这个文件,他都有文件所有者的特权。
如果所有者是 root 的话,那么执行人就有超级用户的特权了,因此不要轻易设置该位。
SUID 特殊权限说明
- SUID 权限仅对可执行文件有效,也就是说 SUID 只能用在 文件 上,不能用在目录
- 执行者对于该程序需要具有
x的可执行权限 - 本权限仅在执行该程序的过程中有效
- 执行者将具有该程序拥有者的权限
SUID example
以/usr/bin/passwd为例:
git用户对于/usr/bin/passwd这个程序具有x权限,表明git用户可以执行passwdpasswd的所有者为rootgit用户执行passwd的过程中会暂时获得root的权限- 因此
/etc/shadow可以被git用户所执行的passwd所修改
SGID
当一个设置了 SGID 位的可执行文件运行时,该文件将具有所属组的特权,任意操作组所能使用的系统资源。
SGID 目录说明
SGID 除了对二进制程序生效,也可以用目录上,而且主要就是在目录上使用这个特殊权限,当一个目录设置了 SGID 权限后,它具有如下功能:
- 用户若对此目录具有
r和x权限,该用户能够进入该目录 - 用户在此目录下的有效用户组将变成该目录的用户组
- 若用户在此目录下拥有
w权限,则用户所创建的新文件的用户组与该目录的用户组相同
SGID 示例
mkdir sgid chmod 4755 sgid ls -l sgidtotal 0drwsr-xr-x 2 yu staff 68 Jun 17 22:53 .drwx------+ 149 yu staff 5066 Jun 17 22:53 .. cp /etc/hosts sgid ls -l /etc/hosts-rw-r--r-- 1 root wheel 262 Feb 27 22:09 /etc/hosts ls -l sgidtotal 4drwsr-xr-x 3 yu staff 102 Jun 17 22:54 .drwx------+ 149 yu staff 5066 Jun 17 22:53 ..-rw-r--r-- 1 yu staff 262 Jun 17 22:54 hosts |
SBIT
Sticky-bit现在仅对目录有效。
SBIT 特殊权限说明
对一个目录设置了Sticky-bit之后,存放在该目录的文件仅准许其属主执行删除、移动等操作,因此该位可以理解为防删除位。
SBIT 示例
cd /tmp && ls -ld .font-unix && rm -rf .font-unixdrwxrwxrwt 2 root root 4096 Jun 9 12:32 .font-unixrm: cannot remove '.font-unix': Operation not permitted |
特殊权限的数值表示
这三种特殊权限的数值表示:
- SUID: 4
- SGID: 2
- SBIT: 1
三种特殊权限可以用单独的一位8进制数值表示:
SUID SGID SBIT 二进制 八进制 说明- - - 000 0 不设置特殊权限- - t 001 1 只设置sticky- s - 010 2 只设置SGID- s t 011 3 只设置SGID和stickys - - 100 4 只设置SUIDs - t 101 5 只设置SUID和stickys s - 110 6 只设置SUID和SGIDs s t 111 7 设置三种特殊权限 |
大写的 S 和 T
如果文件或者文件夹没有x权限,这时s和t对应的位置会变为大写的S和T,实际上也就代表特殊权限无效。
SUID/SGID/SBIT权限设置
使用 chmod 设置这3种特殊权限,和rwx差不多,也有两种方式,一种是以字符,一种是以数字。
字符方式设置权限
- SUID: u+s 和 u-s
- SGID: g+s 和 g-s
- SBIT: o+t 和 o-t
cd /tmp touch suid ls -l suid-rw-r--r-- 1 root root 0 Jun 18 09:22 suid chmod u+s suid ls -l suid-rwSr--r-- 1 root root 0 Jun 18 09:22 suid chmod u+x suid ls -l suid-rwsr--r-- 1 root root 0 Jun 18 09:22 suid |
数字方式设置权限
- SUID: 4rwx
- SGID: 2rwx
- SBIT: 1rwx 和 0rwx
上面rwx对应原来文件或者目录的权限,并且数值方式不能移除 SUID 和 SGID权限。
mkdir sgid-sbit chmod 3777 sgid-sbit ls -ld sgid-sbitdrwxrwsrwt 2 root root 4096 Jun 18 21:39 sgid-sbit |
Real UID 和 Effective UID
Linux 中的进程有2个属性与 SUID 相关,即 RUID 和 EUID,用以控制进程访问文件的权限,查看ps命令手册,可以看到如下信息:
man ps | grep -e "euid\s*EUID\|ruid\s*RUID"euid EUID effective user ID (alias uid).ruid RUID real user ID. |
当一个没有设置 SUID 的程序运行时,RUID 和 EUID 就是当前执行程序的用户的uid,所以 Linux 上基本上除了几个特殊的命令之外(如usr/bin/passwd),程序执行时 RUID 等于 EUID。
而当执行一个有设置 SUID 的程序时,RUID 就是当前执行程序的用uid,而 EUID 则是当前应用程序属主的uid。
测试程序源码
int main(void) { printf("uid = %d, gid = %d, euid = %d, egid = %d\n", getuid(), getgid(), geteuid(), getegid());} |
当前用户名为git,用此帐号将上面源码文件uids.c复制到/tmp目录下,编译生成二进制可执行文件uids,并设置 SUID 位。
cd /tmp ls -l uids.c-rw-rw-r-- 1 git git 158 Jun 19 22:41 uids.c gcc -o uids uids.c chmod 4755 uids ls -l uids-rwsr-xr-x 1 git git 8472 Jun 19 22:41 uids |
当前用户执行
使用当前用户git运行此程序,可以看到其uid和euid值都是当前用户的uid。
./uidsuid = 1000, gid = 1000, euid = 1000, egid = 1000 |
切换用户执行
切换到 root 用户执行此程序,输出的uid为 root 用户的uid,而euid依然是可执行程序属主git的uid值。
cd /tmp/ ls -l uids-rwsr-xr-x 1 git git 8472 Jun 19 22:41 uids ./uidsuid = 0, gid = 0, euid = 1000, egid = 0 id gituid=1000(git) gid=1000(git) groups=1000(git) |
chown 导致文件属性变化
如下图所示,在执行chown root:root /usr/bin/wall命令之后,导致文件属组上的s标记丢失了,如果unix_chkpwd的属性发生变化,也会导致用户密码验证问题,如i3lock在锁屏之后,输入正确密码之后也不能 unlock,就是因为它个unix_chkpwd的用户属性上特殊标志s丢失了。