Linux中文件的特殊权限、隐藏属性与访问控制列表FACL

简介

本篇将介绍 Linux 中文件的特殊权限、隐藏属性与访问控制列表FACL,并用一个场景例子方便读者理解这些命令。

预备工作

  • 为了不影响主机,可使用 Docker 等新创建 Linux 进行操作

  • 创建用户并设置无需密码登录


useradd boy && passwd -d boy

useradd girl && passwd -d girl

useradd singleDog && passwd -d singleDog

1. 文件的特殊权限

1.1 基础

  1. SUID: 能够让二进制程序的执行者临时拥有属主的权限。

  2. SGID: 有两种应用场景,当对二进制程序进行设置时,能够让执行者临时获取到文件所有组的权限;而对目录进行设置时,则是让目录内新创建的文件自动继承该目录原有用户组的名称。

  3. 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容