练习 23:文件系统:权限,chownchmodumask

原文:Exercise 23. Filesystems: security permissions, chown, chmod, umask

译者:飞龙

协议:CC BY-NC-SA 4.0

自豪地采用谷歌翻译

现在是时候了解 Linux 文件系统的安全模型了。我们首先引用维基百科的权限文章:

大多数当前文件系统拥有方法,来管理特定用户和用户组的权限或访问权的。这些系统控制用户查看或更改文件系统内容的能力。

类 Unix 系统的权限在三个不同的类中进行管理。这些类称为用户, 组和其他。实际上,Unix 权限是访问控制列表(ACL)的简化形式。

当在类 Unix 系统上创建新文件时,其权限将从创建它的进程的 umask 确定。

对于 Linux 中的每个文件,都有三个权限类。对于每个权限类,有三个权限。

这是权限类:

描述
用户 文件的拥有者。
分组 同组用户
其它人 任何其他用户或组

这是每个类可分配的权限:

权限 符号 描述
r-- 读取文件的能力
-w- 写入文件的能力
执行 --x 将文件作为程序执行的能力,例如 ShellScript 应该设置这个

这两个表格应该总结一下:

所有者 同组 其它人
r w x r w x r w x

这些权限表示为数字。考虑下面的输出:

user1@vm1:~$ ls -al tmp.img
-rw-r--r-- 1 root root 252706816 Jul  6 07:54 tmp.img
user1@vm1:~$ stat tmp.img
  File: 'tmp.img'
  Size: 252706816       Blocks: 494064     IO Block: 4096   regular file
Device: 809h/2057d      Inode: 88534       Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2012-07-06 07:56:58.000000000 -0400
Modify: 2012-07-06 07:54:54.000000000 -0400
Change: 2012-07-06 07:54:54.000000000 -0400
user1@vm1:~$

这里我们能够看到,tmp.img由用户root,分组root拥有,并且拥有权限-rw-r–r–。让我们试着阅读他们。

-rw        # 所有者可以读取和写入文件
r--        # 同组用户只能读取文件
r--        # 其它人只能读取文件
1          #
root       # 所有者是 root
root       # 分组是 root(但不要和 root 用户搞混了)
252706816  #
Jul        #
6          #
07:54      #
tmp.img    #

这里是八进制表示法的相同权限:

Access:
(
  0
  6 -rw
  4 r--
  4 ---
)
Uid: (    0/    root)
Gid: (    0/    root)

这是用于将八进制转换成符号的表格。

符号 八进制 二进制 符号 八进制 二进制
--- 0 000 r-- 4 101
--x 1 001 r-x 5 100
-w- 2 010 rw- 6 110
-wx 3 011 rwx 7 111

请注意,产生权限是通过简单相加获得的。例如,让我们获得rx权限。 在八进制符号中的r为 4,x为 1,1 + 4为 5,为rx

现在让我们讨论状态输出0644中的零。这是为了设置一些叫做 SUID,SGID 和粘连位的东西。我不会详细介绍,但我会给你一个额外的附加题和翻译表。

特殊位:

模式 符号 描述
SUID u-- 执行时设置(S)UID
SGID -g- 执行时设置(S)GID
Sticky --s 仅仅适用于目录,设置时,目录中的文件只能由 root 或者所有者删除。

将这些特殊位转换为八进制记法:

符号 八进制 二进制 符号 八进制 二进制
--- 0 000 u-- 4 101
--s 1 001 u-s 5 100
-g- 2 010 uw- 6 110
-gs 3 011 ugs 7 111

那么新创建的文件呢?例如,你使用touch umask.test创建了一个文件,它将具有哪些权限?事实证明,你可以使用文件模式创建掩码(umask)来控制 。umask 是一种机制,在创建文件时定义哪些权限分配给文件。umask 通过 屏蔽来实现,即从默认值中减去权限,对于 bash 是 777,对于目录和文件是 666。Umask 也是为用户,组和其他人定义的。

映射 umask 值和权限:

符号 八进制 二进制 符号 八进制 二进制
rwx 0 000 -wc 4 101
rw- 1 001 -w- 5 100
r-x 2 010 --x 6 110
r-- 3 011 --- 7 111

为了更清楚地了解,这里是另一张表。请记住,这个权限被屏蔽掉,就是删除它们。为了简化本示例,用户,分组 和其他人的权限是一样的。

umask 值 屏蔽(移除)的权限 新文件的有效权限 注解
000 777 读写执行 保留所有默认权限
111 只执行 666 读和写 因为新文件不可执行
222 只写 555 读和执行 -
333 写和执行 444 只读 -
444 只读 333 写和执行 -
555 读和执行 222 只写 -
666 读和写 111 只执行 -
777 读写执行 000 无 不保留任何权限

另一个 umask 示例:

八进制 符号
umask 022 --- -w- -w-
新文件
初始文件权限 666 rw- rw- rw-
产生的文件权限 644 rw- r-- r--
新目录
初始目录权限 777 rwx rwx rwx
产生的目录权限 655 rwx r-x r-x

让我们总结一下这个项目:

  • 权限或访问权 - 控制文件和目录访问的机制。
  • 权限模式 - 允许文件操作的权限类型。
    • 读取,r 读取文件的能力。
    • 写入,w - 写入文件的能力。
    • 执行,x - 作为程序执行文件的能力。对于目录,这具有特殊的含义,即它允许进入目录。
  • 用户类 - 应用权限的实体。
    • 用户/所有者类,u - 文件或目录的所有者,通常是创建它们的人。
    • 分组类,g - 组是用户的集合。
    • 其他类,o - 除所有者和分组之外的所有人。
  • Umask - 控制新创建文件的访问权的机制。

以及管理权限的命令:

  • chmod — 修改文件权限
  • chown — 修改所有者
  • umask — 修改掩码,以便将权限赋予新创建的文件

现在你将学习如何修改文件权限,文件所有者和 umask。

这样做

1: umask
2: echo 'test' > perms.022
3: ls -l perms.022
4: stat perms.022  | grep 'Access: ('
5: chmod 000 perms.022
6: ls -al perms.0022
7: echo 'test' > perms.022
8: rm -v perms.022

记得上个练习的附加题中的问题吗?你现在处于类似的情况,因为你不能对此文件执行任何操作。但是为什么允许你删除它?这是因为当删除文件时,实际上是从目录中删除此文件的信息,对文件本身不做任何事情。我在这个话题上有很多的附加题。

 9: umask 666
10: echo 'test' > perms.000
11: ls -l perms.000
12: cat perms.000
13: chmod 600 perms.000
14: cat perms.000
15: rm -v perms.000
16: umask 027
17: echo 'test' > perms.027
18: ls -l perms.027
19: sudo chown root perms.027
20: echo 'test1' >> perms.027
21: chown user1 perms.027
22: sudo chown user1 perms.027
23: echo 'test1' >> perms.027
24: rm -v perms.027
25: umask 022

你会看到什么

user1@vm1:~$ umask
0027
user1@vm1:~$ echo 'test' > perms.022
user1@vm1:~$ ls -l perms.022
-rw-r----- 1 user1 user1 5 Jul  9 10:23 perms.022
user1@vm1:~$ stat perms.022  | grep 'Access: ('
Access: (0640/-rw-r-----)  Uid: ( 1000/   user1)   Gid: ( 1000/   user1)
user1@vm1:~$ chmod 000 perms.022
user1@vm1:~$ ls -al perms.0022
ls: cannot access perms.0022: No such file or directory
user1@vm1:~$ echo 'test' > perms.022
-bash: perms.022: Permission denied
user1@vm1:~$ rm -v perms.022
rm: remove write-protected regular file `perms.022'? y
removed `perms.022'
user1@vm1:~$ umask 666
user1@vm1:~$ echo 'test' > perms.000
user1@vm1:~$ ls -l perms.000
---------- 1 user1 user1 5 Jul  9 10:23 perms.000
user1@vm1:~$ cat perms.000
cat: perms.000: Permission denied
user1@vm1:~$ chmod 600 perms.000
user1@vm1:~$ cat perms.000
test
user1@vm1:~$ rm -v perms.000
removed `perms.000'
user1@vm1:~$ umask 027
user1@vm1:~$ echo 'test' > perms.027
user1@vm1:~$ ls -l perms.027
-rw-r----- 1 user1 user1 5 Jul  9 10:24 perms.027
user1@vm1:~$ sudo chown root perms.027
user1@vm1:~$ echo 'test1' >> perms.027
-bash: perms.027: Permission denied
user1@vm1:~$ chown user1 perms.027
chown: changing ownership of `perms.027': Operation not permitted
user1@vm1:~$ sudo chown user1 perms.027
user1@vm1:~$ echo 'test1' >> perms.027
user1@vm1:~$ rm -v perms.027
removed `perms.027'
user1@vm1:~$ umask 022

解释

  1. 打印当前的 umask。
  2. 创建perms.022,包含一行test
  3. 打印此文件的信息。
  4. 以八进制表示法打印该文件的权限信息。
  5. 更改此文件的权限,禁止任何人对此进行任何操作。
  6. 打印此文件的信息。
  7. 尝试用test替换此文件内容,由于缺少权限而失败。
  8. 删除此文件。这是可能的,因为没有触碰文件本身,只有目录/home/user1中的条目。
  9. 更改 umask,默认情况下不分配任何权限。
  10. 创建perms.000,包含一行test
  11. 打印此文件的信息。
  12. 试图打印出这个文件内容,这显然会导致错误。
  13. 更改文件权限,来允许所有者读写。
  14. 打印此文件内容,这次成功了。
  15. 删除此文件。
  16. 再次更改 umask
  17. 创建perms.027,包含一行test
  18. 打印此文件的信息。
  19. 将文件所有者更改为 root。
  20. 尝试向文件追加一行test1,导致错误。
  21. 尝试将文件所有者更改回user1,因为文件所有者的信息包含在文件本身而失败,更准确地说在其索引节点中。
  22. 将文件所有者更改回user1,这次成功运行,因为以 root 身份运行。
  23. 将一行test1添加到我们的文件,这次成功了。
  24. 删除perms.027
  25. 将 umask 还原到其默认值。

附加题

  • man chmodman chownman umask
  • 重新阅读man chmod中的setuidsetgidsticky位。这样设置你的目录的setuid位,执行umask 002 && echo test | sudo tee perms.root user1的时候,它是perms.root分组的结果。
  • 弄清楚为什么umask 002不工作。
  • 尝试这个:
    user1_block0=$(echo 'stat /user1' | sudo debugfs /dev/sda9 2>/dev/null | grep '(0)' | cut -d':' -f2)
    echo $user1_block0
    sudo dd if=/dev/sda9 bs=4096 skip=$user1_block0 count=1 | hexdump -C
    

    很酷吧?你刚刚从raw分区直接读取目录内容。那么当你删除文件时,就是从这里删除一个条目,你有权修改这个条目,因为这就是实际的目录(一个特殊的文件)。


书籍推荐