文件权限
Linux 的安全性
Linux 安全系统的核心是用户账户。每个能访问 Linux 系统的用户都会被分配一个唯一的用户账户。
- 用户对系统中各种对象的访问权限取决于他们登录系统时所用的账户。
- 用户权限是通过创建用户时分配的用户ID( user ID,UID)来跟踪的,用户在登录系统时是使用登录名来代替 UID 登录的。
/etc/passwd
文件
Linux 系统使用一个专门的文件
/etc/passwd
来匹配登录名与对应的 UID 值。该文件包含了一些与用户有关的信息。
/etc/passwd
文件内容:
[root@localhost ~]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
...
root 用户账户是 Linux 系统的管理员,为其固定分配的UID是0。
文件各字段含义如下:
- 登录用户名 ;
- 用户密码 ;
- 用户账户的 UID(数字形式);
- 用户账户的组 ID(数字形式);
- 用户账户的文本描述(备注字段);
- 用户 $HOME 目录的位置 ;
- 用户的默认 shell 。
Linux 系统会为各种各样的功能创建不同的用户账户,而这些账户并非真正的人类用户,它们被称其为系统账户,它们是系统中运行的各种服务进程访问资源使用的特殊账户。
所有运行在后台的服务都需要通过一个系统用户账户登录到 Linux 系统中。
注意事项:
/etc/passwd
是一个标准的文本文件。可以使用任何文本编辑器直接在其中手动进行用户管理(比如添加、修改或删除用户账户),但这样做极其危险。如果/etc/passwd
文件受损,系统无法读取文件内容,则会导致用户(即便 root 用户)无法正常登录。
/etc/shadow
文件
/etc/shadow
文件对 Linux 系统密码管理提供了更多的控制。只有 root 用户才能访问/etc/shadow
文件,这使其与/etc/passwd
相比要安全许多。
/etc/passwd
文件内容:
[root@localhost etc]# cat /etc/shadow
root:$1$fSRcHFBk$0u9srHhY5fHNnC9SKdWjx0:19328:0:99999:7:::
bin:*:17835:0:99999:7:::
daemon:*:17835:0:99999:7:::
adm:*:17835:0:99999:7:::
lp:*:17835:0:99999:7:::
...
文件各字段含义如下:
- 登录名,对应于
/etc/passwd
文件中的登录名。 - 加密后的密码。
- 自上次修改密码后已经过去的天数( 从 1970 年 1 月 1 日 开始计算 )。
- 多少天后才能更改密码。
- 多少天后必须更改密码。
- 密码过期前提前多少天提醒用户更改密码。
- 密码过期后多少天禁用用户账户。
- 用户账户被禁用的日期( 以从 1970 年 1 月 1 日到当时的天数表示 )。
- 预留给以后使用的字段。
- 登录名,对应于
有了 shadow 密码系统,就可以更好地控制用户密码了,比如控制用户多久更改一次密码,以及如果密码未更新的话,什么时候禁用该账户。
添加新用户
用来向 Linux 系统添加新用户的主要工具是
useradd
。该命令可以一次性轻松创建新用户账户并设置用户的 $HOME 目录结构。
useradd
常用命令选项:
选项 | 描述 |
---|---|
-c<备注> | 给新用户添加备注。 |
-d<登入目录> | 指定用户登入时的起始目录。 |
-D | 变更预设值。 |
-e<有效期限> | 指定帐号的有效期限。 |
-f<缓冲天数> | 指定在密码过期后多少天即关闭该帐号。 |
-g<群组> | 指定用户所属的群组。 |
-G<群组> | 指定用户所属的附加群组。 |
-m | 制定用户的登入目录。 |
-M | 不要自动建立用户的登入目录。 |
-n | 取消建立以用户名称为名的群组。 |
-r | 建立系统帐号。 |
-s<shell> | 指定用户登入后所使用的shell。 |
-u<uid> | 指定用户ID。 |
- 应用示例:
# 1.添加一般用户。
[root@localhost ~]# useradd taketo
# 2.为添加用户指定相应的用户组。
[root@localhost ~]# useradd -g root taketo
删除用户
如果从系统中删除用户,
userdel
可以满足这个需求。
- 在默认情况下,
userdel
命令只删除/etc/passwd
和/etc/shadow
文件的用户信息,属于该账户的文件会被保留。 userdel
常用命令选项:
选项 | 描述 |
---|---|
-r | 删除用户登入目录以及目录中所有文件。 |
- 应用示例:
# 1.删除用户账号。
[root@localhost ~]# userdel taketo
- 注意事项:在有大量用户的环境中使用 -r 选项要特别小心。**你可能不知道用户是否在个人的 $HOME 目录中存放了其他用户或程序用到的*重要文件*。**所以,在删除之前一定要检查清楚。
修改用户
Linux 提供了一些工具来修改已有用户账户的信息。
命令 | 描述 |
---|---|
usermod | 修改用户账户字段。 |
passwd | 修改已有用户的密码。 |
chpasswd | 从文件中读取登录名及密码并更新密码。 |
chage | 修改密码的过期日期。 |
chfn | 修改用户账户的备注信息。 |
chsh | 修改用户账户的默认登录 shell。 |
usermod
usermod
常用命令选项:
选项 | 描述 |
---|---|
-d<登入目录> | 修改用户登入时的目录。 |
-g<群组> | 修改用户所属的群组。 |
-G<群组> | 修改用户所属的附加群组。 |
-l<帐号名称> | 修改用户帐号名称。 |
-L | 锁定用户密码,使密码无效。 |
-p | 修改账户密码。 |
-u<uid> | 修改用户ID。 |
-U | 解除密码锁定。 |
passwd 和 chpasswd
- 如果只使用
passwd
命令,则修改的是你自己的密码。系统中的任何用户都能修改自己的密码,但只有 root 用户才有权限修改别人的密码。 passwd
常用命令选项:
选项 | 描述 |
---|---|
-e | 可以强制用户下次登录时修改密码。 |
- 应用示例:
# 1.root 修改指定用户密码。
[root@localhost ~]# passwd taketo
Changing password for user taketo.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
- 如果需要为系统中的大量用户修改密码,那么
chpasswd
命令可以让你事半功倍,它能从标准输入自动读取一系列以冒号分隔的登录名和密码对偶,自动对密码加密,然后为用户账户设置密码。 - 应用示例:
# 其中 users.txt 文件内容为 username:password 。
[root@localhost tmp]# chpasswd < users.txt
chsh、chfn 和 chage
chsh
命令可以快速修改默认的用户登录 shell(使用时必须用 shell 的全路径作为参数,不能只用 shell 名)。- 应用示例:
# 1.默认登录的 shell 改为 /bin/csh。
[root@localhost tmp]# chsh -s /bin/csh taketo
Changing shell for root.
Shell not changed.
chfn
命令提供了在/etc/passwd
文件的备注字段中保存信息的标准方法。chage
命令可用于帮助管理用户账户的有效期。chage
常用命令选项:
选项 | 描述 |
---|---|
-d | 设置自上次修改密码后的天数。 |
-E | 设置密码过期日期。 |
-I | 设置密码过期多少天后锁定账户。 |
-m | 设置更改密码的最小间隔天数。 |
-M | 设置密码的最大有效天数。 |
-W | 设置密码过期前多久开始出现提醒信息。 |
chage
命令的一个好用的功能是设置账户的过期日期。有了它,就可以创建在特定日期自动过期的临时用户,再也不用操心删除用户了。(过期账户跟锁定账户类似:账户仍然存在,但用户无法用其登录。)
使用 Linux 组
用户账户在控制单个用户安全性方面还不错,但涉及共享资源的一组用户时就捉襟见肘了。为了解决这个问题,Linux 系统采用了另一个安全概念——组。组权限允许多个用户对系统对象(比如文件、目录或设备等)共享一组权限,且每个组都有唯一的 GID。
/etc/group
文件
与用户账户类似,组信息也保存在一个文件中。
/etc/group
文件包含系统中每个组的信息。
- /etc/group 文件内容:
[root@localhost tmp]# cat /etc/group
root:x:0:
bin:x:1:
daemon:x:2:
sys:x:3:
adm:x:4:
...
taketo:x:1009:
taketo:x:1010:
...
对于系统账户组,为其分配的 GID 值低于 500,而普通用户组的 GID 则从 500 开始分配。
/etc/group
有 4 个字段:- 组名;
- 组密码;
- GID;
- 属于该组的用户列表。
注意事项:
/etc/group
文件是一个标准的文本文件,因此可以手动编辑该文件来添加和修改组成员关系。但一定要小心,千万不要出现任何拼写错误,否则可能会损坏文件,引发系统故障。更安全的做法是使用usermod
命令向组中添加用户(在将用户添加到不同的组之前,必须先创建组)。
创建新组
groupadd
命令用于创建新组。
- 应用示例:
# 1.创建一个新的组,并添加组ID。
[root@localhost ~]# groupadd -g 344 shared
[root@localhost ~]# tail -5 /etc/group
jan2:x:1009:
jan3:x:1010:
shared:x:344:
...
注意事项:
- 在创建新组时,默认不为其分配任何用户,但可以用
usermod
命令来解决。 - 如果更改了已登录系统的用户所属的组,则该用户必须注销后重新登录,这样新的组关系才能生效。
- 使用 -g 选项,则指定的组名会替换掉在
/etc/passwd
文件中为该用户分配的主要组。 - 使用 -G 选项,则会将该组加入该用户的属组列表,不会影响主要组。
- 在创建新组时,默认不为其分配任何用户,但可以用
修改组
groupmod
命令用于更改群组识别码或名称。
groupmod
常用命令选项:
选项 | 描述 |
---|---|
-g <群组识别码> | 设置欲使用的群组识别码(即 GID)。 |
-n <新群组名称> | 设置欲使用的群组名称。 |
- 应用示例:
# 1.设置新的组名。
[root@localhost ~]# groupmod -n sharing shared
[root@localhost ~]# tail -5 /etc/group
jan2:x:1009:
jan3:x:1010:
sharing:x:344:
...
- 修改组名时,GID 和组成员保持不变,只有组名会改变。由于所有的安全权限均基于 GID ,因此可以随意改变组名,不会影响文件的安全性。
理解文件权限
使用文件权限符号
- 使用
ls
命令查看 Linux 系统中的文件、目录和设备权限。
[root@localhost tmp]# ls -l
total 12
-rw-r--r-- 1 root root 48 May 13 09:15 1.log
-rw-r--r-- 1 root root 276 May 13 09:39 test.log
-rw-r--r-- 1 root root 23 May 26 22:30 users.txt
- 输出结果的第一个字段就是描述文件和目录权限的编码,其中:
- 第一个字符表示对象的类型:
选项 | 描述 |
---|---|
- | 代表文件; |
d | 代表目录; |
l | 代表链接; |
c | 代表字符设备; |
b | 代表块设备; |
p | 代表具名管道; |
s | 代表网络套接字; |
- 之后 3 组字符的编码,每一组定义了 3 种访问权限
选项 | 描述 |
---|---|
r | 代表对象是可读的; |
w | 代表对象是可写的; |
x | 代表对象是可执行的; |
如果没有某种权限,则在该权限位会出现连字符。这 3 组权限分别对应对象的 3 个安全级别为:
- 对象的属主;
- 对象的属组;
- 系统其他用户。
示意图:
# - R W X R W - R - -
- 对象类型
R W X 属主
R W - 属组
R - - 其他用户
默认文件权限
umask
命令用来设置新建文件和目录的默认权限。
- 应用示例:
# 1. touch 命令使用分配当前用户的默认权限创建了新的文件。
[root@localhost tt]# touch newfile
[root@localhost tt]# ls -al newfile
-rw-r--r-- 1 root root 0 May 27 08:00 newfile
# 2. umask 命令可以显示和设置默认权限。
[root@localhost tt]# umask
0022
umask
命令的设置方法不是那么简单明了,0022 第一位数代表了一项安全特性,接下来的 3 个数位表示文件或目录对应的umask
八进制值。- 八进制模式的安全设置先获取
rwx
权限值,然后将其转换成 3 位(bit)二进制值,用一个八进制值来表示。在二进制表示中,每个位置代表一个二进制位。 - 因此,如果读权限是唯一置位的权限,则权限值是
r - -
,换成二进制值就是 100,对应的八进制值是 4。 - Linux 文件权限编码:
权限 | 二进制值 | 八进制值 | 描述 |
---|---|---|---|
--- | 000 | 0 | 没有任何权限。 |
--x | 001 | 1 | 只有执行权限。 |
-w- | 010 | 2 | 只有写入权限。 |
-wx | 011 | 3 | 有写入和执行权限。 |
r-- | 100 | 4 | 只有读取权限。 |
r-x | 101 | 5 | 有读取和执行权限。 |
rw- | 110 | 6 | 有读取和写入权限。 |
rwx | 111 | 7 | 有全部权限(读取、写入和执行)。 |
- 八进制模式先取得权限的八进制值,然后再把这 3 种安全级别(属主、属组和其他用户)对应的八进制值顺序列出。因此八进制模式的值 664 代表了属主和属组成员都有读取和写入权限,而其他用户只有读取权限。
- 问题点:知道了八进制模式权限如何工作,那么
umask
值是 0022 ,而所创建的文件八进制权限则是 664,是如何得来的呢? umask
值只是个掩码,它会屏蔽掉不想授予该安全级别的权限。对于文件而言,全权限值是 666 (所有用户都有读写权限);对目录而言,全权限值是 777 (所有用户都有读写执行权限)。上面的例子,文件一开始的权限是 666 ,减去umask
值 022 之后,剩下的文件权限就成了 644。
更改安全设置
修改权限
chmod
命令可以修改文件和目录的安全设置,其参数允许使用八进制模式或符号模式来进行安全设置。
与通常用到的 3 组权限字符不同,
chmod
命令采用的是另一种方法。命令格式:
chmod
[ 权限作用对象 ] [ 权限操作 ] [ 要设置的权限 ]权限作用对象:
u
代表用户;g
代表组;o
代表其他用户;a
代表上述所有。
权限操作:
- 符号
+
代表增加权限; - 符号
-
代表移除权限; - 符号
=
代表设置权限;
- 符号
要设置的权限(除了
rwx
权限,额外还有):X
:仅当对象是目录或者已有执行权限时才赋予执行权限;s
:在执行时设置 SUID 或 GID;t
:设置粘滞位;u
:设置属主权限;g
:设置属组权限;o
:设置其他用户权限。
应用示例:
# 1.使用符号模式,设置所有人都能读取。
[root@localhost tt]# chmod ugo+r newfile
[root@localhost tt]# ls -al newfile
-rw-r--r-- 1 root root 0 May 27 08:00 newfile
# 2.使用八进制值设置。
[root@localhost tt]# chmod 777 newfile
[root@localhost tt]# ls -al newfile
-rwxrwxrwx 1 root root 0 May 27 08:00 newfile
改变所属关系
有时你需要改变文件的属主,比如有人离职,或是开发人员创建了一个需要在产品环境种归属于系统账户的应用程序。
chown
可以修改文件的属主,chgrp
可以修改文件的默认属组。
- 应用示例:
# 1.查看当前属主。
[root@localhost tt]# ls -l newfile
-rwxrwxrwx 1 root root 0 May 27 08:00 newfile
# 2.修改属主。
[root@localhost tt]# chown taketo newfile
[root@localhost tt]# ls -l newfile
-rwxrwxrwx 1 taketo root 0 May 27 08:00 newfile
# 3.修改属组。
[root@localhost tt]# chgrp sharing newfile
[root@localhost tt]# ls -l newfile
-rwxrwxrwx 1 taketo sharing 0 May 27 08:00 newfile
共享文件
Linux 系统中共享文件的方法是创建组。但对于一个完整的文件共享环境而言,事情会复杂很多。
创建新文件时,Linux 会用默认的 UID 和 GID 来给文件分配权限。要想让其他用户也能访问文件,要么修改所有用户一级的安全权限,要么给文件分配一个包含其他用户的新默认数组,如果想在大范围内创建并共享文件,这会十分烦琐。幸好有一种简单的解决方法:
Linux 为每个文件和目录存储 3 个额外的信息位:
- SUID ( set user ID ):当用户执行该文件时,程序会以文件属主的权限运行。
- SGID ( set group ID ):对文件而言,程序会以文件属组的权限运行;对目录而言,该目录中创建的新文件会以目录的属组作为默认属组。
- 粘滞位( sticky bit ):应用于目录时,只有文件属主可以删除或重命名该目录中的文件。
SGID 位对文件共享非常重要。启用 SGID 位后,可以强制在共享目录中创建的新文件都属于该目录的属组,这个组也就成了每个用户的属组。
可以通过
chmod
命令设置 SGID (可以使用八进制模式或符号模式)。SUID、SGID 和粘滞位的八进制值:
二进制值 | 八进制值 | 描述 |
---|---|---|
000 | 0 | 清除所有位。 |
001 | 1 | 设置粘滞位。 |
010 | 2 | 设置 SGID 位。 |
011 | 3 | 设置 SGID 位和粘滞位。 |
100 | 4 | 设置 SUID 位。 |
101 | 5 | 设置 SUID 位和粘滞位。 |
110 | 6 | 设置 SUID 位和 SGID 位。 |
111 | 7 | 设置所有位。 |
- 应用示例:
# 1.创建希望共享的目录。
[root@localhost tt]# mkdir testdir
[root@localhost tt]# ls -l
total 4
drwxr-xr-x 2 root root 4096 May 27 09:18 testdir
# 2.修改目录的默认属组,使其包含所有需要共享文件的用户。
[root@localhost tt]# chgrp shared testdir
# 3.通过符号模式,设置目录的 SGID 位,保证目录中新建的文件都以 shared 作为默认属组。
[root@localhost tt]# chmod g+s testdir
[root@localhost tt]# ls -l
total 4
drwxr-sr-x 2 root shared 4096 May 27 09:18 testdir
# 4.为了让环境正常工作,所有成员都要设置他们的 usmask 值,这里改成 002 ,所以文件对属组都是可写的。
[root@localhost tt]# umask 002
# 5.新文件会沿用目录的默认属组,而不是用户账户的默认属组(现在 shared 组的所有用户都能访问这个文件了)。
[root@localhost tt]# cd testdir/
[root@localhost testdir]# touch 1.log
[root@localhost testdir]# ls -l
total 0
-rw-rw-r-- 1 root shared 0 May 27 09:19 1.log
访问控制列表
在一个复杂的商业环境中,对于文件和目录,不同的组需要不同的权限,基本权限方法解决不了这个问题。Linux 开发者设计出了一种更先进的文件和目录安全方法:访问控制列表( access control list ,ACL)。ACL 允许指定包含多个用户或组的列表以及为其分配的权限。
- 和基本安全方法一样,ACL 权限使用相同的读取、写入和执行权限位,但现在可以分配给多个用户和组。
- 可以使用
setfacl
命令和getfacl
命令在 Linux 种实现 ACL 特性。 getfacl
命令能够查看分配给文件或目录的 ACL:
[root@localhost tmp]# getfacl 1.log
# file: 1.log
# owner: root
# group: root
user::rw-
group::r--
other::r--
setfacl
命令可以为用户或组分权限。setfacl
常用命令选项:
选项 | 描述 |
---|---|
-m | 修改分配给文件或目录的权限。 |
-x | 删除特定权限。 |
3 种定义规则:
- 为用户分配权限:
u [ser]:uid:perms
- 为组分配权限:
g [roup]:gid:perms
- 为其他用户分配权限:
o[ther]::perms
- 为用户分配权限:
应用示例:
# 1.查看文件原始属组权限。
[root@localhost tmp]# ls -l 1.log
-rw-r--r--+ 1 root root 48 May 13 09:15 1.log
# 2.为 1.log 文件添加了 test 分组的读写执行权限。
[root@localhost tmp]# setfacl -m g:test:rwx 1.log
[root@localhost tmp]# ls -l 1.log
-rw-rwxr--+ 1 root root 48 May 13 09:15 1.log
# 3.查看 ACL 。
[root@localhost tmp]# getfacl 1.log
# file: 1.log
# owner: root
# group: root
user::rw-
group::r--
group:test:rwx
mask::rwx
other::r--
# 4.删除权限。
[root@localhost tmp]# setfacl -x g:test 1.log
[root@localhost tmp]# getfacl 1.log
# file: 1.log
# owner: root
# group: root
user::rw-
group::r--
mask::r--
other::r--
- Linux 也允许对目录设置默认 ACL,在该目录中创建的文件会自动继承。
- 应用示例:
# 1.要设置目录默认的ACL,可以正常定义规则前加 d: 。
[root@localhost tmp]# setfacl -m d:g:test:rwx /home/tmp/
# 2.查看指定目录下新文件的ACL。
[root@localhost tmp]# touch 2.log
[root@localhost tmp]# getfacl 2.log
# file: 2.log
# owner: root
# group: root
user::rw-
group::r-x #effective:r--
group:test:rwx #effective:rw-
mask::rw-
other::r--