简介
本篇将介绍 Linux 中文件的特殊权限、隐藏属性与访问控制列表FACL,并用一个场景例子方便读者理解这些命令。
预备工作
为了不影响主机,可使用 Docker 等新创建 Linux 进行操作
创建用户并设置无需密码登录
useradd boy && passwd -d boy
useradd girl && passwd -d girl
useradd singleDog && passwd -d singleDog
1. 文件的特殊权限
1.1 基础
SUID: 能够让二进制程序的执行者临时拥有属主的权限。
SGID: 有两种应用场景,当对二进制程序进行设置时,能够让执行者临时获取到文件所有组的权限;而对目录进行设置时,则是让目录内新创建的文件自动继承该目录原有用户组的名称。
SBIT: 粘滞位,当时文件使用时,该文件只能被其所有者执行删除操作;当对某个目录使用时,该目录中的文件就只能被其所有者执行删除操作。
chmod u+s /tmp/test # 设置 SUID 权限
chmod u-s /tmp/test # 取消 SUID 权限
chmod g+s /tmp/test # 设置 GUID 权限
chmod g-s /tmp/test # 取消 GUID 权限
chmod o+t /tmp/test # 设置 SBIT 权限
chmod o-t /tmp/test # 取消 SBIT 权限
SUID、SGID 与 SBIT 也有对应的数字法表示,分别是 4、2、1
chmod 7777 /tmp/test # 设置所有权限
被设置的特殊权限会在权限列表中的“可执行”位的位置体现出来。对于SUID和SGID,原先有执行权限的是小写s,如果没有执行权限则是大写S;对于SBIT,原先有执行权限是小写t,没有执行权限则是大写T。
# 先初始化权限
rm -rf /tmp/test
touch /tmp/test
ls -l /tmp/test # -rw-r--r--
chmod 0777 /tmp/test # 对新创的文件,效果等于 chmod 777 /tmp/test
ls -l /tmp/test # -rwxrwxrwx
# 现在开始注意每组权限中的可执行位 x
# 设置 SUID 权限
chmod u+s /tmp/test
ls -l /tmp/test # -rwsrwxrwx 注意 u 位的 x 位变成了 s
# 设置 GUID 权限
chmod g+s /tmp/test
ls -l /tmp/test # -rwsrwsrwx 注意 g 位的 x 位也变成了 s
# 设置 SBIT 权限
chmod o+t /tmp/test
ls -l /tmp/test # -rwsrwsrwt 注意 o 位的 x 位变成了 t
# 把特殊权限和执行权限都去掉
chmod 0666 /tmp/test
ls -l /tmp/test # -rw-rw-rw-
# 设置 SUID 权限
chmod u+s /tmp/test
ls -l /tmp/test # -rwSrw-rw- 注意 u 位的 x 位变成了 S
# 设置 GUID 权限
chmod g+s /tmp/test
ls -l /tmp/test # -rwSrwSrw- 注意 g 位的 x 位也变成了 S
# 设置 SBIT 权限
chmod o+t /tmp/test
ls -l /tmp/test # -rwSrwSrwT 注意 o 位的 x 位变成了 T
1.2 场景运用
1.2.1 SUID 的运用
利用 SUID 使得 girl 可以以 boy 权限执行 boy 能力
- boy 创建一程序 boyPay
su - boy
echo "pay by boy" > /tmp/boy_pay.txt
chmod 600 /tmp/boy_pay.txt # 让 g 和 o 都不能读写,保存后面生成的程序,需用 boy 执行才不会报错。
ls -l /tmp/boy_pay.txt # -rw-------
vi /tmp/boyPay.c
#include <stdio.h>
int main()
{
FILE *fp = NULL;
char buff[255];
fp = fopen("/tmp/boy_pay.txt", "r");
fgets(buff, 255, (FILE *)fp);
printf("%s", buff);
return 0;
}
# 生成二进制程序
gcc /tmp/boyPay.c -o /tmp/boyPay
ls -l /tmp/boyPay # -rwxrwxr-x
# 执行 boyPay
/tmp/boyPay # pay by boy
- girl 想使用 boy 的 boyPay ,发现不可用,很生气
su - girl
# 执行 pay
/tmp/boyPay # Segmentation fault
- boy 马上为 boyPay 添加 SUID 权限
su - boy
chmod u+s /tmp/boyPay
ls -l /tmp/boyPay # -rwsrwxr-x 注意 u 中 x 位变成了 s
- girl 执行 boy 的 boyPay ,心情变好
su - girl
# 执行 pay
/tmp/boyPay # pay by boy
1.2.2 SGID 的运用
利用 SGID 实现:boy 在属于 girl 的开放文件夹下创建的内容,还是属于 girl 组。
- girl 在 /tmp 在创建文件夹 girlFunc 并添加 777 权限。
su - girl
mkdir /tmp/girlFunc
chmod 777 /tmp/girlFunc
ls -ld /tmp/girlFunc # drwxrwxrwx
- boy 在里面写个日记
su - boy
echo "I bought an expensive Garage Kit ^-^" > /tmp/girlFunc/boyDiary.txt
ls -l /tmp/girlFunc/boyDiary.txt # -rw-rw-r-- 1 boy boy
# 这里可以用到,文件所有组是 boy, 其他人无写权限
# boy 做过分点,不仅让其他人无法写,还不给读
chmod o-r /tmp/girlFunc/boyDiary.txt
ls -l /tmp/girlFunc/boyDiary.txt # -rw-rw---- 1 boy boy
- girl 跑来查日记,发现在自家文件夹下,居然不可读写 boy 的日记
su - girl
cat /tmp/girlFunc/boyDiary.txt # cat: /tmp/girlFunc/boyDiary.txt: Permission denied
echo "I'm very angry now !!! -- by your girl" >> /tmp/girlFunc/boyDiary.txt # -bash: /tmp/girlFunc/boyDiary.txt: Permission denied
- 然后 girl 为文件夹设置了 SGID 权限
chmod g+s /tmp/girlFunc
ls -ld /tmp/girlFunc # drwxrwsrwx 注意 g 中 x 位变成了 s
- 第二天 boy 又用同样的方法写了日记
su - boy
echo "I bought another expensive Garage Kit ^-^" > /tmp/girlFunc/boyDiary2.txt
ls -l /tmp/girlFunc/boyDiary2.txt # -rw-rw-r-- 1 boy girl
chmod o-r /tmp/girlFunc/boyDiary2.txt
ls -l /tmp/girlFunc/boyDiary2.txt # -rw-rw---- 1 boy girl
- girl 查日记,boy 成功被吓死
su - girl
cat /tmp/girlFunc/boyDiary2.txt # I bought another expensive Garage Kit ^-^
echo "I'm very angry now -- by your girl" >> /tmp/girlFunc/boyDiary2.txt
# I bought another expensive Garage Kit ^-^
# I'm very angry now -- by your girl
1.2.3 SBIT 的运用
利用 SBIT 实现谁创建的文件谁删除
girl 有个特点,时不时会用 rm -rf *
boy 认为日记应该放至公共目录中,因为目录的属主可以删除目录下任何(哪怕没权限的)文件
boy 说服 girl 后,他们决定把日志丢在 boy 的程序员朋友 singleDog 家的 singleDogHome 目录中
singleDog 梦中惊坐起
boy 找到 singleDog ,和他讨论了事情的经过,singleDog 对 boy 的遭遇表示同情,很不情愿地把 singleDogHome 开放出来,存放他们的日记
girl 要求 boy 写的日记必须 girl 可读写,而默认情况下可写就是可删除
为此,singleDog 好人做尽,为目录添加 SBIT 权限
su - singleDog
mkdir /tmp/singleDogHome
ls -ld /tmp/singleDogHome/ # drwxrwsrws
chmod o+t /tmp/singleDogHome
ls -ld /tmp/singleDogHome/ # drwxrwsrwt 注意 o 的 x 位变成了 t
- boy 写日记
su - boy
echo "Tody I just Learn" > /tmp/singleDogHome/boyDiary.txt
ls -l /tmp/singleDogHome/boyDiary.txt # -rw-rw-r-- 1 boy boy
# 完成 girl 的要求
chmod 666 /tmp/singleDogHome/boyDiary.txt
ls -l /tmp/singleDogHome/boyDiary.txt # -rw-rw-rw- 1 boy boy
echo "san jiu tian xia di yi" > /tmp/singleDogHome/boyDiary2.txt
chmod 666 /tmp/singleDogHome/boyDiary2.txt
- girl 写日记
su - girl
echo "I bought a nice bag today" > /tmp/singleDogHome/girlDiary.txt
- girl 查看 boy 日记,发现可读写,不过删不了
su - girl
ls -l /tmp/singleDogHome
# -rw-rw-r-- 1 boy boy 23 6月 11 07:10 boyDiary2.txt
# -rw-rw-rw- 1 boy boy 37 6月 11 07:09 boyDiary.txt
# -rw-rw-r-- 1 girl girl 26 6月 11 07:09 girlDiary.txt
cat /tmp/singleDogHome/boyDiary.txt # Tody I just Learn
echo "ok -- by your girl" >> /tmp/singleDogHome/boyDiary.txt # 可正常写入
# 看一下另一个
cat /tmp/singleDogHome/boyDiary2.txt # san jiu tian xia di yi
# ...
# 突然
rm -rf /tmp/singleDogHome/*
# rm: cannot remove ‘/tmp/singleDogHome/boyDiary2.txt’: Operation not permitted
# rm: cannot remove ‘/tmp/singleDogHome/boyDiary.txt’: Operation not permitted
# 发现只删除了自己的日记
ls -l /tmp/singleDogHome
# -rw-rw-r-- 1 boy boy 23 6月 11 07:10 boyDiary2.txt
# -rw-rw-rw- 1 boy boy 37 6月 11 07:09 boyDiary.txt
2. 文件的隐藏属性
2.1 基础
如果您的 linux 中没有带
chattr
,测需要安装e2fsprogs
工具包CentOS:
yum -y install e2fsprogs
- Ubuntu:
apt-get install e2fsprogs
-
设置用法与常用参数解析:
用法 chattr [-RVf] [-+=aAcCdDeijsStTu] [-v version] files...
每个参数前的
+
就是添加属性,-
就是删除属性i: 只有 root 可以设置,无法对文件进行修改与删除;若对目录设置了该参数,则仅能修改其中的子文件内容而不能新建或删除文件
a: 只有 root 可以设置,仅允许补充(追加)内容,无法覆盖/删除内容(Append Only)
A: 不再修改这个文件或目录的最后访问时间(atime)
b: 不再修改文件或目录的存取时间
查询用法: lsattr [-RVadlv] [files...]
echo "test" > test.txt
ls -l test.txt # -rw-rw-r--
lsattr test.txt # -------------e--
# 添加 i
chattr +i test.txt
ls -l test.txt # -rw-rw-r--
lsattr test.txt # ----i--------e--
rm -rf test.txt # rm: cannot remove ‘test.txt’: Operation not permitted
# 去删 i
chattr -i test.txt # -------------e--
rm -rf test.txt # 成功删除
2.2 场景运用
利用 chattr 的 a 参数设置文件只可被追加内容。其实像用户访问日志就可以设此属性,文件只会被添加访问记录,别人无法修改或删除,保留证据。
- girl 创建一存钱罐文件 girlPiggyBank ,只可存,不可取
su - girl
touch /tmp/girlPiggyBank
chmod 777 /tmp/girlPiggyBank # 在 +a 前做,不然加了 a 后,连权限都无法改
sudo chattr +a /tmp/girlPiggyBank # i 和 a 操作必须用 root
lsattr /tmp/girlPiggyBank # -----a-------e--
# 存钱
echo "10" >> /tmp/girlPiggyBank
cat /tmp/girlPiggyBank # 10
# 无法修改和删除, root 也不行
sudo vi /tmp/girlPiggyBank # 在保存时报 "/tmp/girlPiggyBank" E212: Can't open file for writing
sudo rm -f /tmp/girlPiggyBank # rm: cannot remove ‘/tmp/girlPiggyBank’: Operation not permitted
- boy 也是只能往 girlPiggyBank 存钱
su - body
# 存钱
echo "10" >> /tmp/girlPiggyBank
echo "10" >> /tmp/girlPiggyBank
echo "10" >> /tmp/girlPiggyBank
echo "10" >> /tmp/girlPiggyBank
cat /tmp/girlPiggyBank # 10\n10\n10\n10\n10
# 无法修改和删除, root 也不行
sudo vi /tmp/girlPiggyBank # 在保存时报 "/tmp/girlPiggyBank" E212: Can't open file for writing
sudo rm -f /tmp/girlPiggyBank # rm: cannot remove ‘/tmp/girlPiggyBank’: Operation not permitted
- girl 上去解开 a 属性后就可以摔罐了
su - girl
sudo chattr -a /tmp/girlPiggyBank
rm -rf /tmp/girlPiggyBank # 操作成功
3. 文件访问控制列表 FACL
FACL 全称为 File Access Control Lists,文件访问控制列表,可对某个指定的用户或组进行对某文件的单独的权限控制。如果针对某个目录设置了ACL,则目录中的文件会继承其权限;若针对文件设置了ACL,则文件不再继承其所在目录的权限。
3.1 基础
-
FACL 设置命令与常用参数详解
用法: setfacl [-bkndRLP] { -m|-M|-x|-X ... } file ...
m: 修改权限
x: 删除某个权限
b: 删除所有权限
R: 递归子目录
-
FACL 查询命令
用法: getfacl [-aceEsRLPtpndvh] file ...
ls -l 用命也可查看文件是否有 FACL,不过只能是否有(看权限信息的结尾是否有+号),不能知道有什么
# 单独为用户 girl 增加 /tmp/test.txt 文件的读写权限
setfacl -m u:girl:rw /tmp/test.txt
# 单独为用户组 boy 递归增加 /tmp/singleDogHome 目录全部权限
setfacl -Rm g:boy:rwx /tmp/singleDogHome
# 删除用户 fang 对 /tmp/test.txt 文件的读写权限
setfacl -x u:girl /tmp/test.txt
# 查看 /tmp/singleDogHome 权限
ls -l /tmp/test/txt # rw_rw_r__+ 尾部多了个 + 号
getfacl /tmp/singleDogHome
- 会出现如下内容,注意多了个
group:boy:rwx
getfacl: Removing leading '/' from absolute path names
# file: tmp/singleDogHome
# owner: singleDog
# group: singleDog
# flags: --t
user::rwx
group::rwx
group:boy:rwx
mask::rwx
other::rwx
3.2 场景运用
利用 setfacl 单独为某一用户设置权限
- 之前 boy 为了 让 girl 可以使用他的 boyPay,为程序 boyPay 设置的 SUID 权限
su - girl
/tmp/boyPay # pay by boy
- singleDog 看见后试了一下,结果实现钱富自由
su - singleDog
/tmp/boyPay # pay by boy
- girl 十分不愿意,要求 payPay 只能为她用,boy 只好删除 SUID,改用 setfacl 实现
su - boy
ls -l /tmp/boyPay # -rwsrwxr-x
chmod u-s /tmp/boyPay
ls -l /tmp/boyPay # -rwxrwxr-x u 的 x 位从 s 变回了 x
# boyPay 程序里读取的是 /tmp/boy_pay.txt 里的内容,因些 setfacl 要对 /tmp/boy_pay.txt 用
ls -l /tmp/boy_pay.txt # -rw-------
setfacl -m u:girl:rw /tmp/boy_pay.txt
ls -l /tmp/boy_pay.txt # -rw-rw----+ 多了个 + 号
getfacl /tmp/boy_pay.txt # 会多一行 user:girl:rw-
- girl 开始支付,满脸写着开心
su - girl
/tmp/boyPay # pay by boy
- singleDog 也想用,梦突然就醒了
su - singleDog
/tmp/boyPay # Segmentation fault