文件特殊权限SUID和SGID和SBIT

前言

特殊权限尽量少修改! 不安全!
(很久以前写的一篇学习笔记, 一直没有整理

作用

给执行该文件的用户临时赋予另一个用户(组)的权限。

比如设置密码

1
2
3
ll /etc/shadow /usr/bin/passwd 
----------. 1 root root 1232 10月 6 05:47 /etc/shadow
-rwsr-xr-x. 1 root root 27832 6月 10 2014 /usr/bin/passwd

/etc/shadow文件只能被root用户修改。
但是借助passwd命令, 普通用户可以临时变成root来执行这个passwd命令,
进而修改/etc/shadow文件。

切换用户 SUID

只有可以执行的二进制程序才能设定SUID权限。
SUID可以看成是Switch User ID(一个瞎猜), 就是切换用户ID.

  1. 创建两个文件file1file2
  2. 添加SUID权限, 或者chmod u+s file
  3. 取消SUID权限, 或者chmod u-s file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 创建两个文件
touch file1 file2 && ll
# -rw-rw-r--. 1 ahao ahao 0 11月 21 21:13 file1
# -rw-rw-r--. 1 ahao ahao 0 11月 21 21:13 file2

# 2. 添加SUID权限, 或者chmod u+s file
chmod 4755 file1 && chmod 4655 file2 && ll
# -rwsr-xr-x. 1 ahao ahao 0 11月 21 21:13 file1
# -rwSr-xr-x. 1 ahao ahao 0 11月 21 21:13 file2

# 3. 取消SUID权限, 或者chmod u-s file
chmod 0755 file1 && chmod 0655 file2 && ll
# -rwxr-xr-x. 1 ahao ahao 0 11月 21 21:13 file1
# -rw-r-xr-x. 1 ahao ahao 0 11月 21 21:13 file2

可以看到x执行权限的位置被s替换了。
47554655的区别在于文件本身有没有x执行权限。
并且可以得知s=S+x, 并且注意!!! 大写S是没有意义的。
只有小写s才能被执行, 才能正确设定SUID权限。

切换用户组 SGID

SUID一样, 区别在于用户会临时赋予文件所属用户组group的身份, 而不是用户user身份。Switch Group ID

比如**locate命令**

1
2
3
ll /usr/bin/locate /var/lib/mlocate/mlocate.db 
# -rwx--s--x. 1 root slocate 40512 11月 21 23:21 /usr/bin/locate
# -rw-r-----. 1 root slocate 3678432 11月 21 23:21 /var/lib/mlocate/mlocate.db

/var/lib/mlocate/mlocate.db文件只能被slocate组查看。
但是借助locate命令, 普通用户可以临时变成slocate来执行这个locate命令,
进而查看/var/lib/mlocate/mlocate.db文件。

除了和SUID差不多的功能外。
SGID对目录还有另一个功能。
就是进入该目录后, 用户的用户组会变成SGID对应的用户组

  1. root用户创建test目录并赋予777权限
  2. ahao用户在test目录下创建file1
  3. root用户为test目录赋予SGID权限
  4. ahao用户在赋予SGIDtest目录下创建file2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 1. root用户创建test目录并赋予777权限
mkdir ~ahao/test && chmod 777 ~ahao/test && ll -d ~ahao/test
# drwxrwxrwx. 2 root root 6 11月 21 23:39 /home/ahao/test

# 2. ahao用户在test目录下创建file1
su - ahao
touch ~ahao/test/file1 && ll ~ahao/test
# -rw-rw-r--. 1 ahao ahao 0 11月 21 23:43 file1

# 3. root用户为test目录赋予SGID权限, 或者chmod g+s file
su -
chmod 2777 ~ahao/test && ll -d ~ahao/test/
# drwxrwsrwx. 2 root root 19 11月 21 23:43 /home/ahao/test/


# 4. ahao用户在赋予SGID的test目录下创建file2
su - ahao
touch ~ahao/test/file2 && ll ~ahao/test
# -rw-rw-r--. 1 ahao ahao 0 11月 21 23:43 file1
# -rw-rw-r--. 1 ahao root 0 11月 21 23:45 file2

可以看到赋予SGID后, ahao用户创建的file2的所属组是root

防止被删除 sticky bit ( SBIT )

除了userSUIDgroupSGID外, 还有othersticky bit

sticky bit有两个要求

  1. 只对目录有效。
  2. 文件权限为rwxrwxrwx, 也就是777的权限。
    比如/tmp目录。

那么任何用户都能对目录下的文件进行读写执行操作, 这是很不安全的。
比如一个目录, 允许用户(other)创建文件(写权限), 拥有了写权限的用户也同样拥有了删除权限。
也就是说在777权限的目录下, A用户创建的文件可能被B用户删除。
sticky bit就是为了解决这个问题。
赋予目录sticky bit后。

  1. 只有root有删除权限。
  2. 其他用户只能删除自己创建的文件。
  3. 其他用户拥有写权限。

下面举个例子

  1. root用户创建test目录并赋予777权限。
  2. root用户创建file文件。
  3. ahao用户删除file文件成功, 因为ahao用户对test目录有w写权限。
  4. root用户对test目录赋予sticky bit权限。
  5. root用户创建file文件。
  6. ahao用户删除file文件失败, 即使ahao用户对test目录有w写权限。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 1. root用户创建test目录并赋予777权限
mkdir ~ahao/test && chmod 777 ~ahao/test/ && ll -d ~ahao/test/
# drwxrwxrwx. 2 root root 6 11月 22 23:23 /home/ahao/test/

# 2. root用户创建file文件
echo "hello" > ~ahao/test/file && ll ~ahao/test/
# -rw-r--r--. 1 root root 6 11月 22 23:26 file

# 3. ahao用户删除file文件成功, 因为ahao用户对test目录有w写权限
su - ahao && rm -rf ~ahao/test/file && ll ~ahao/test/

# 4. root用户对test目录赋予sticky bit权限
su -
# chmod 0777 ~ahao/test/ # 取消sticky bit, 或chmod o-t ~ahao/test/
chmod 1777 ~ahao/test/ # 赋予sticky bit, 或chmod o+t ~ahao/test/
ll -d ~ahao/test/
drwxrwxrwt. 2 root root 6 11月 22 23:27 /home/ahao/test/

# 5. root用户创建file文件
echo "hello" > ~ahao/test/file && ll ~ahao/test/
# -rw-r--r--. 1 root root 6 11月 22 23:32 file

# 6. ahao用户删除file文件失败, 即使ahao用户对test目录有w写权限
su - ahao
rm -rf ~ahao/test/file
# rm: 无法删除"/home/ahao/test/file": 不允许的操作

如果不能删除, 那我能不能覆盖掉呢? echo '' > file
我在Ubuntu尝试了不能, 但是以前在CentOS试过好像可以.

检查系统新增的SUID和SGID文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 1. 先查找所有拥有SUID(4)和SGID(2)的文件
find / -perm -4000 -o -perm -2000 > /tmp/suid.list

# 2. 编写Shell脚本
#!/bin/bash
# 2.1 查找所有拥有SUID(4)或SGID(2)的文件, 并保存到临时文件suid.check中
find / -perm -4000 -o -perm -2000 > /tmp/suid.check

for line in $(cat /tmp/suid.check)
do
# 2.3 遍历临时文件suid.check中的记录, 和最初查找到的文件/tmp/suid.list进行比较。
grep $line /tmp/suid.list > /dev/null
# 2.4 不存在则写入log文件中
if [ "$?" != "0" ];then
echo "$i isn't in listfile! " >> /tmp/suid_log_$(date +%F)
fi
done
rm -rf /tmp/suid.check
echo "/tmp/suid_log_$(date +%F)"
cat /tmp/suid_log_$(date +%F)