Linux系统中的权限控制

本章将和大家分享Linux系统中的权限控制。废话不多说,下面我们直接进入主题。

一、基础知识

Linux作为一种多用户的操作系统(服务器系统),允许多个用户同时登陆到系统上,并响应每个用户的请求。

任何需要使用操作系统的用户,都需要一个系统账号,账号分为:管理员账号与普通用户账号。 

在Linux中,操作系统根据UID来判断用户,而不是用户名,只要id为0就是管理员,哪怕有多个id为0的账号

系统在新建账号时,会根据账号类型,自动分配递增账号的UID与GID (用户身份编号,组编号),也可自行分配。通常情况下,应当保证UID与GID唯一且不重复

1、组的类别

在Linux中,每个用户必须有一个主组。当创建账号时,系统会自动创建一个同名组作为该账户的主组。用户必须属于一个且只有一个主组。用户可以属于零个或者多个附加组。

2、用户与组的配置文件

在Linux中,万物皆文件,所以用户与组也以配置文件的形式保存在系统中,以下为用户和组的主要配置文件详解:

-   /etc/passwd:用户及其属性信息(名称、 UID、主组ID等)
-   /etc/group:组及其属性信息
-   /etc/shadow:用户密码及其相关属性
-   /etc/gshadow:组密码及其相关属性

1)passwd文件格式

依次含义为(用 : 分割):

  • 登录用户名
  • 密码
  • UID
  • GID
  • 全名或注释
  • 用户主目录
  • 用户默认使用shell

2)group文件格式

依次含义为(用 : 分割):

  • 群组名称
  • 群组密码(通常不需要设定,密码被记录在/etc/gshadow)
  • GID:群组ID
  • 组成员(以“,”来分割,该账户没有附加组所以为空)

3)shadow文件格式

依次含义为(用 : 分割):

  • 登录用户名
  • 密码(通常使用shad512加密)
  • 从1970年1月1日起计算到现在为止密码最近一次被更改的时间
  • 密码再过几天就可以被修改(0表示随时可改)
  • 密码几天后必须变更(99999表示永不过期)
  • 密码过期前多久提示用户
  • 密码过期多久后账户将被锁定
  • 多少天后账户将失效(从1970-1-1算起)

4)gshadow文件格式

依次含义为(用 : 分割):

  • 群组名称
  • 群组密码
  • 组管理员列表
  • 当前用户的附加组

二、用户账号管理

在Linux,管理员在默认情况下为root账户,UID=0。普通用户UID默认范围为1-65535。在centos 6中,新建用户,默认系统用户的UID范围为1-499,普通用户为500+。

在centos 7中,系统用户范围为1-999,普通用户为1000+。对系统的操作权限由用户决定

通常对用户账号的操作分为添加,修改,删除。

1、添加账户

通过 useradd 命令来添加用户,语法如下:

useradd [opentions] login

参数说明:

  • -u UID 自定义UID(默认系统递增)
  • -o 配合-u 选项,不检查UID的唯一性(不建议)
  • -g GID:指明用户所属基本组,可为组名,也可以GID
  • -c comment 指定一段注释性描述。
  • -d 目录 指定用户主目录,如果此目录不存在,则同时使用-m选项,可以创建主目录。
  • -g 用户组 指定用户所属的用户组(主组)。
  • -G 用户组,用户组 指定用户所属的附加组。
  • -s Shell文件 指定用户的登录Shell。
  • -u 用户号 指定用户的用户号,如果同时有-o选项,则可以重复使用其他用户的标识号。

示例1(常用):

useradd -d /usr/ddz ddz

创建了一个用户ddz,并将他的家目录(主目录)设置到/usr/ddz

示例2:

groupadd 组名 添加用户组
   -g :添加组时指定组ID
groupmod 组名 修改用户组信息
   -n :修改组名
   -g :修改组ID
groupdel 组名 删除组
*如果一个组下有用户,那么这个组是无法删除的。
useradd -s /sbin/bash -g root -G mage,wang ddz

此命令新建了一个用户ddz,设置该用户使用的shell为/sbin/bash,设置他的主组属于root用户组,设置附加组为mage和wang。(当设置组时,要保证组已经存在,否则请先创建该组

小技巧:

  • 增加用户账号就是在/etc/passwd文件中为新用户增加一条记录,同时系统会自动更新其他系统文件如/etc/shadow,/etc/group等。 
  • 通常情况创建账户,账户ID会按照最大的值递增,但是递增的值必须在最大范围内。
  • 在部署软件时,通常会需要使用账户,所以需要指定UID,来部署所有的账号都用同一个UID,来方便管理。
  • newusers [passwd格式文件] 用于批量创建账户,只需要每一列账户信息格式,按照passwd中书写,之后上传到Linux中替换即可。
  • chpasswd 批量修改用户口令。将文件格式写为:user:passwd 。每行一个,之后导入Linux即可。
  • 创建账户的默认值设定位于: /etc/default/useradd文件中,该文件记录了创建用户账户时的默认信息,可通过修改该文件来修改创建账户时的信息。

2、删除帐号

如果一个用户的账号不再使用,可以从系统中删除。删除用户账号就是要将/etc/passwd等系统文件中的该用户记录删除,必要时还需删除用户的主目录。

通常在运维工作中,一般使用让账号失效,或者修改账户名的方式,来便捷的操作账号。

删除一个已有的用户账号使用userdel命令,其格式如下:

userdel 选项 用户名

常用的选项是 -r,它的作用是把用户的主目录一起删除。

例如:

userdel -r sam

此命令删除用户sam在系统文件中(主要是/etc/passwd, /etc/shadow, /etc/group等)的记录,同时删除用户的主目录。

删除账号需要该账户没有人在使用,才能删除成功。请使用命令删除,不要去手动改文件。

3、修改帐号

修改用户账号就是根据实际情况更改用户的有关属性,如用户号、主目录、用户组、登录Shell等。

修改已有用户的信息使用usermod命令,其格式如下:

usermod 选项 用户名

常用的选项包括-c, -d, -m, -g, -G, -s, -u以及-o等,这些选项的意义与useradd命令中的选项一样,可以为用户指定新的资源值。

另外,有些系统可以使用选项:-l 新用户名。这个选项指定一个新的账号,即将原来的用户名改为新的用户名。

例如:

usermod -s /bin/ksh -d /home/z -g developer sam

此命令将用户sam的登录Shell修改为ksh,主目录改为/home/z,用户组改为developer。

4、查询账号口令

id [opentions] [User]

相关参数:

  • -u:显示UID
  • -g:显示GID
  • -G:显示用户所属的组ID
  • -n:显示名称

5、用户口令管理

用户管理的一项重要内容是用户口令的管理。用户账号刚创建时没有口令,但是被系统锁定,无法使用(在passwd文件中,密码列显示为!!或者!表示用户被锁定,是无法登陆的),必须为其指定口令后才可以使用,即使是指定空口令。

指定和修改用户口令的Shell命令是passwd。超级用户可以为自己和其他用户指定口令,普通用户只能用它修改自己的口令。命令的格式为:

passwd 选项 用户名

可使用的选项:

  • -l 锁定口令,即禁用账号。
  • -u 口令解锁。
  • -d 使账号无口令。
  • -f 强迫用户下次登录时修改口令。

如果默认用户名,则修改当前用户的口令。

例如,假设当前用户是sam,则下面的命令修改该用户自己的口令:

passwd 
Old password:****** 
New password:******* 
Re-enter new password:*******

如果是超级用户,可以用下列形式指定任何用户的口令:

passwd sam 
New password:******* 
Re-enter new password:*******

普通用户修改自己的口令时,passwd命令会先询问原口令,验证后再要求用户输入两遍新口令,如果两次输入的口令一致,则将这个口令指定给用户;而超级用户为用户指定口令时,就不需要知道原口令。

为了系统安全起见,用户应该选择比较复杂的口令,例如最好使用8位长的口令,口令中包含有大写、小写字母和数字,并且应该与姓名、生日等不相同。

为用户指定空口令时,执行下列形式的命令:

passwd -d sam

此命令将用户sam的口令删除,这样用户sam下一次登录时,系统就不再询问口令。

passwd命令还可以用-l(lock)选项锁定某一用户,使其不能登录,例如:

passwd -l sam

利用组来简化授权操作,当对整个组授权时,整个组下的账号权限都会进行修改

用户相关的其他指令:

chfn [USER] 修改用户的备注文档

chsh [Shell] 修改用户的指定shell

三、用户组的管理

每个用户都有一个用户组,系统可以对一个用户组中的所有用户进行集中管理。不同 Linux 系统对用户组的规定有所不同,如 Linux 下的用户属于与它同名的用户组,这个用户组在创建用户时同时创建。 

用户组的管理涉及用户组的添加、删除和修改。组的添加、删除和修改实际上就是对/etc/group文件的更新。

1、增加组

增加一个新的用户组使用groupadd命令,其格式如下:

groupadd 选项 用户组

可以使用的选项有:

  • -g GID 指定新用户组的组标识号(GID)。
  • -o 一般与-g选项同时使用,表示新用户组的GID可以与系统已有用户组的GID相同。
  • -r 创建系统组。

示例1:

groupadd group1

此命令向系统中增加了一个新组group1,新组的组标识号是在当前已有的最大组标识号的基础上加1。

示例2:

groupadd -g 101 group2

此命令向系统中增加了一个新组group2,同时指定新组的组标识号是101。

2、删除组

如果要删除一个已有的用户组,使用groupdel命令,其格式如下:

groupdel 用户组

示例:

groupdel group1

此命令从系统中删除组group1。要想删除组,要确保该组不是主组,才能把这个组删掉。

3、修改组

修改用户组的属性使用groupmod命令,其语法如下:

groupmod 选项 用户组

常用的选项有:

  • -g GID 为用户组指定新的组标识号。
  • -o 与-g选项同时使用,用户组的新GID可以与系统已有用户组的GID相同。
  • -n 新用户组 将用户组的名字改为新名字。

示例1:

groupmod -g 102 group2

此命令将组group2的组标识号修改为102。

示例2:

groupmod -g 10000 -n group3 group2

此命令将组group2的标识号改为10000,组名修改为group3。

4、切换组(临时切换主组)

如果一个用户同时属于多个用户组,那么用户可以在用户组之间切换,以便具有其他用户组的权限。

用户可以在登录后,使用命令newgrp切换到其他用户组。例如:

newgrp root

这条命令将当前用户切换到root用户组,前提条件是root用户组确实是该用户的主组或附加组。类似于用户账号的管理,用户组的管理也可以通过集成的系统管理工具来完成。

更改查看组成员

可以通过以下命令,来更改和查看组中的成员:

groupmems [opentions] [action]

参数如下:

  • -g 更改为指定组(只有root可以使用)
  • -a 指定用户加入组
  • -d 从组中删除该用户
  • -p 从组中清除所有成员
  • -l 显示组成员列表

示例1:

groupmems -l -g root

此命令表示查看root组中存在的成员。

示例2:

groupmems -a Father -g root

此命令表示将Father用户加入root组中。

小技巧:

  • 一个用户可以加入不同的组,但是有且只有一个主组。
  • 一个用户的权限为他所属的多个组的累加权限 。假设user账户附加组group1 = write group2 = read ,那么user就拥有 write + read权限。
  • 组和用户的关系是多对多 一个用户可以有多个组,一个组也可以有多个用户。
  • 在windows中,只有管理员才允许对用户组进行操作,但在Linux中,只要有组的口令,就可以让账号进入组。
  • root组的权限与普通组权限大致相同,账号并不是加入root组就能获得用户权限。

四、文件的权限控制

1、文件权限与归属

在Linux系统中,每个文件都有归属的所有者和所有组,并且规定了文件的所有者、所有组以及其他人对文件所拥有的读(r)、写(w)、执行(x)等权限。

对于一般文件来说,权限比较容易理解:“可读”表示能够读取文件的实际内容;“可写”表示能够编辑、新增、修改、删除文件的实际内容;“可执行”则表示能够运行一个脚本程序。

但是,对于目录文件来说,理解其权限设置来就不那么容易了。很多资深Linux用户其实也没有真正搞明白。

对目录文件来说,“可读”表示能够读取目录内的文件列表;“可写”表示能够在目录内新增、删除、重命名文件;而“可执行”则表示能够进入该目录。

读写执行权限对于文件与目录可执行命令的区别:

文件的读、写、执行权限英文全称分别是read、write、execute,可以简写为r、w、x,亦可分别用数字4、2、1来表示,文件所有者,所属组及其他用户权限之间无关联。

文件权限的字符与数字表示:

文件权限的数字法表示基于字符(rwx)的权限计算而来,其目的是简化权限的表示方式。例如,若某个文件的权限为**7**则代表可读、可写、可执行(4+2+1);若权限为6则代表可读、可写(4+2)。我们来看这样一个例子,现在有这样一个文件,其所属者拥有可读、可写、可执行的权限,其所属组拥有可读、可写的权限,而其他人只有可读的权限。那么,这个文件的权限就是rwxrw-r--,数字法表示即为764。不过大家千万别再将这三个数字相加,计算出7+6+4=17的结果,这是小学的数学加减法,不是Linux系统的权限数字表示法,三者之间没有互通关系。 

以rw-r-x-w-权限为例进行讲解,要想转换成数字法,首先要进行各个位之上的数字替代,如图(字符与数字权限转换示意图)所示:

减号是占位符,代表这里没有权限,数字法用0表示,也就是说rw-转换后是420,r-x转换后是401,-w-转换后是020,三组数字之间每组数字进行相加后得出652便是转换后的数字法权限。

而数字法转回到字符权限相比来说就有些难度了,以652权限为例进行讲解。首先数字6是由4+2得到的,不可能是4+1+1,因为每个权限只能占一位,所以数字5则是4+1得到的,2便是本身,没有权限即是空值0。

数字与字符权限转换示意图:

心中牢记:文件的所属者、所属组和其他人权限之间无关联,不要写成rrwwx—-的样子,一定要把rwx权限位对应到正确的位置,写成rw-r-x-w-。

通过ls命令查看到的文件属性信息:

包含了文件的类型(第一个字符表示文件的类型,d表示文件夹,减号表示普通文件)、访问权限、所有者(属主)、所属组(属组)、占用的磁盘大小、最后修改时间和文件名称等信息。通过分析可知,该文件的类型为普通文件,所有者权限为可读、可写(rw-),所属组权限为可读(r--),除此以外的其他人也只有可读权限(r--),文件的磁盘占用大小是34298字节,最近一次的修改时间为4月2日的凌晨23分,文件的名称为install.log。

其中排在权限前面的减号(-)是文件类型,新手经常会把它跟无权限混淆。尽管在Linux系统中一切都是文件,但是不同的文件由于作用不同,因此类型也不尽相同,有一点点像Windows系统的后缀名。常见的文件类型包括有:普通文件(-)、目录文件(d)、链接文件(l)、管道文件(p)、块设备文件(b)以及字符设备文件(c)。

普通文件的范围特别广泛,比如纯文本信息、服务配置信息、日志信息以及Shell脚本等等都包含在内,所以几乎在每个目录下都能看到普通文件(-)和目录文件(d)的身影。块设备文件(b)和字符设备文件(c)一般是指硬件设备,比如鼠标、键盘、光驱、硬盘等等都是设备文件,主要集中在/dev/目录中最为常见,不过其实很少会对鼠标键盘进行硬件级别的管理吧~

2、文件的特殊权限

在复杂多变的生产环境中,单纯设置文件的rwx权限无法满足我们对安全和灵活性的需求,因此便有了SUID、SGID与SBIT的特殊权限位。这是一种对文件权限进行设置的特殊功能,可以与一般权限同时使用,以弥补一般权限不能实现的功能。

下面具体解释这3个特殊权限位的功能以及用法。

1)SUID

SUID是一种对二进制程序进行设置的特殊权限,能够让二进制程序的执行者临时拥有所属主的权限(仅对拥有执行权限的二进制程序有效)。例如,所有用户都可以执行passwd命令来修改自己的用户密码,而用户密码保存在/etc/shadow文件中。仔细查看这个文件就会发现它的默认权限是000,也就是说除了root管理员以外,所有用户都没有查看或编辑该文件的权限。但是,在使用passwd命令时如果加上SUID特殊权限位,就可让普通用户临时获得程序所属者的身份,把变更的密码信息写入到shadow文件中。这很像在古装剧中见到的手持尚方宝剑的钦差大臣,他手持的尚方宝剑代表的是皇上的权威,因此可以惩戒贪官,但这并不意味着他永久成为了皇上。因此这只是一种有条件的、临时的特殊权限授权方法。

查看passwd命令属性时发现所属者的权限由rwx变成了rws,其中x改变成s就意味着该文件被赋予了SUID权限。另外有读者会好奇,那么如果原本的权限是rw-呢?如果原先权限位上没有x执行权限,那么被赋予特殊权限后将变成大写的S

[root@localhost ~]# ls -l /etc/shadow
----------. 1 root root 1345 7月  22 22:06 /etc/shadow
[root@localhost ~]# ls -l /bin/passwd
-rwsr-xr-x. 1 root root 27856 4月   1 2020 /bin/passwd

注意:一定要小心这个权限,因为一旦某个命令文件被设置上了SUID权限,那么就意味着凡是执行的人都可以临时获取到更高的权限,千万不要设置到vim、cat、rm等命令上面!!!

2)SGID

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

第一种功能是参考SUID而设计的,不同点在于执行程序的用户获取的不再是文件所属者的临时权限,而是获取到文件所属组的权限。举例来说,在早期的Linux系统中,/dev/kmem是一个字符设备文件,用于存储内核程序要访问的数据,权限为:

cr--r----- 1 root system 2, 1 Feb 11 2017 kmem

大家看出问题了吗?除了root管理员或属于system组成员外,其他用户都没有读取该文件的权限。由于在平时我们需要查看系统的进程状态,为了能够获取到进程的状态信息,可在用于查看系统进程状态的ps命令文件上增加SGID特殊权限位。查看ps命令文件的属性信息:

-r-xr-sr-x 1 bin system 59346 Feb 11 2017 ps

这样一来,由于ps命令被增加了SGID特殊权限位,所以当用户执行该命令时,也就临时获取到了system用户组的权限,从而顺利地读取到了设备文件。

前文提到,每个文件都有其归属的所属者和所属组,当创建或传送一个文件后,这个文件就会自动归属于执行这个操作的用户(即该用户是文件的所有者)。如果现在需要在一个部门内设置共享目录,让部门内的所有人员都能够读取目录中的内容,那么就可以创建部门共享目录后,在该目录上设置SGID特殊权限位。这样,部门内的任何人员在里面创建的任何文件都会归属于该目录的所属组,而不再是自己的基本用户组。此时,用到的就是SGID的第二个功能,即在某个目录中创建的文件自动继承该目录的用户组(只可以对目录进行设置)。

[root@localhost ~]# cd /tmp
[root@localhost tmp]# mkdir testdir
[root@localhost tmp]# ls -ald testdir
drwxr-xr-x. 2 root root 6 7月  23 22:27 testdir
[root@localhost tmp]# chmod -R 777 testdir
[root@localhost tmp]# chmod -R g+s testdir
[root@localhost tmp]# ls -ald testdir
drwxrwsrwx. 2 root root 6 7月  23 22:27 testdir

在使用上述命令设置好目录的777权限(确保普通用户可以向其中写入文件),并为该目录设置了SGID特殊权限位后,就可以切换至一个普通用户,然后尝试在该目录中创建文件,并查看新创建的文件是否会继承新创建的文件所在的目录的所属组名称:

[root@localhost ~]# su - dev1
上一次登录:二 7月 23 22:34:01 CST 2024pts/0 上
[dev1@localhost ~]$ cd /tmp/testdir
[dev1@localhost testdir]$ echo "linuxprobe.com" > test
[dev1@localhost testdir]$ ls -al test
-rw-r--r--. 1 dev1 root 15 7月  23 22:35 test

除了上面提到的SGID的这两个功能,再介绍两个与本小节内容相关的命令:chmod和chown。

chmod命令用于设置文件的一般权限及特殊权限,英文全称为:“change mode”,语法格式为:“chmod [参数] 文件名”。

这是一个与日常设置文件权限强相关的命令,例如要把一个文件的权限设置成其所有者可读可写可执行、所属组可读可写、其他人没有任何权限,则相应的字符法表示为rwxrw----,其对应的数字法表示为760。

[root@linuxprobe ~]# ls -l anaconda-ks.cfg 
-rw-------. 1 root root 1407 Jul 21 05:09 anaconda-ks.cfg
[root@linuxprobe ~]# chmod 760 anaconda-ks.cfg 
[root@linuxprobe ~]# ls -l anaconda-ks.cfg 
-rwxrw----. 1 root root 1407 Jul 21 05:09 anaconda-ks.cfg

chown命令用于设置文件的所有者和所有组,英文全称为:“change own”,语法格式为:“chown 所有者:所有组 文件名”。

chmod和chown命令是用于修改文件属性和权限的最常用命令,它们还有一个特别的共性,就是针对目录进行操作时需要加上大写参数-R来表示递归操作,即对目录内所有的文件进行整体操作。

使用“所有者:所有组”的格式轻松把刚刚那个文件的所属信息修改一下,变更后的效果如下:

[root@linuxprobe ~]# chown linuxprobe:linuxprobe anaconda-ks.cfg 
[root@linuxprobe ~]# ls -l anaconda-ks.cfg 
-rwxrw----. 1 linuxprobe linuxprobe 1407 Jul 21 05:09 anaconda-ks.cfg

3)SBIT

现在,大学里的很多老师都要求学生将作业上传到服务器的特定共享目录中,但总是有几个“破坏分子”喜欢删除其他同学的作业,这时就要设置SBIT(Sticky Bit)特殊权限位了(也可以称之为特殊权限位之粘滞位)。SBIT特殊权限位可确保用户只能删除自己的文件,而不能删除其他用户的文件。换句话说,当对某个目录设置了SBIT粘滞位权限后,那么该目录中的文件就只能被其所有者执行删除操作了。

最初不知道是哪位非资深技术人员将Sticky Bit直译成了“粘滞位”,刘遄老师建议将其称为“保护位”,这既好记,又能立刻让人了解它的作用。RHEL 8系统中的/tmp作为一个共享文件的目录,默认已经设置了SBIT特殊权限位,因此除非是该目录的所有者,否则无法删除这里面的文件。

与前面所讲的SUID和SGID权限显示方法不同,当目录被设置SBIT特殊权限位后,文件的其他人权限部分的x执行权限就会被替换成t或者T,原本有x执行权限则会写成t,原本没有x执行权限则会被写成T。

/tmp目录上的SBIT权限默认已经存在,体现为“其他用户”权限字段的权限变为rwt:

[root@linuxprobe ~]# ls -ald /tmp
drwxrwxrwt. 17 root root 4096 Oct 28 00:29 /tmp

其实,文件能否被删除并不取决于自身的权限,而是看其所在目录是否有写入权限。为了避免现在很多读者不放心,所以下面的命令还是赋予了这个test文件最大的777权限(rwxrwxrwx):

[root@linuxprobe ~]# cd /tmp
[root@linuxprobe tmp]# echo "Welcome to linuxprobe.com" > test
[root@linuxprobe tmp]# chmod 777 test
[root@linuxprobe tmp]# ls -al test 
-rwxrwxrwx. 1 root root 26 Oct 29 14:29 test

随后,切换到一个普通用户身份下,尝试删除这个其他人创建的文件就会发现,即便读、写、执行权限全开,但是由于SBIT特殊权限位的缘故,依然无法删除该文件:

[root@linuxprobe tmp]# su - linuxprobe
[linuxprobe@linuxprobe ~]$ cd /tmp
[linuxprobe@linuxprobe tmp]$ rm -f test
rm: cannot remove 'test': Operation not permitted

工作中对特殊权限善加使用,能够实现很多巧妙的功能,chmod命令设置特殊权限时的参数如下:

参数 作用
u+s 设置SUID权限
u-s 取消SUID权限
g+s 设置SGID权限
g-s 取消SGID权限
o+t 设置SBIT权限
o-t 取消SBIT权限

切换回root管理员的身份下,在家目录中创建一个名为linux的新目录,随后设置上SBIT权限吧:

[linuxprobe@linuxprobe tmp]$ exit
Logout
[root@linuxprobe tmp]# cd ~
[root@linuxprobe ~]# mkdir linux
[root@linuxprobe ~]# chmod -R o+t linux/
[root@linuxprobe ~]# ls -ld linux/
drwxr-xr-t. 2 root root 6 Feb 11 19:34 linux/

上面的o+t参数是在一般权限已经设置完毕的前提下,又新增了一项特殊权限,那如果我们想一般权限和特殊权限一起设置,有什么高效率的方法呢?

其实SUID、SGID与SBIT也有对应的数字法表示,分别是4、2、1。也就是说777还不是最大权限,满权限应该是7777,第一个数字代表的是特殊权限位。既然知道了数字表示法是由“特殊权限+一般权限”构成的,那就以上面linux目录的权限为例梳理下计算方法吧。

在“rwxr-xr-t”权限中,最后一位是t,代表该文件的一般权限为“rwxr-xr-x”,并带有SBIT特殊权限。对于读(r)、写(w)、执行(x)权限的数字计算方法大家应该很熟悉了——即755,而SBIT特殊权限位是1,合并后结果为1755。

再增加点难度,如果权限是“rwsrwSr--”呢?首先不要慌,看到大写S代表原先没有执行权限,因此一般权限为“rwxrw-r--”,数字法计算后结果是764。带有的SUID和SGID特殊权限数字法表示是4和2,心算得出结果是6,合并后结果为6764。

权限的字符表示法转数字表示法:

将数字法转换成字符法难度略微高一些,以5537为例为大家讲解。首先特殊权限的5是由4+1组成的,意味着是有SUID和SBIT。SUID和SGID的写法是原先有执行权限则是小写s,如果没有执行权限则是大写S,而SBIT的写法则是原先有执行权限是小写t,没有执行权限是大写T。一般权限的537进行字符转换后应为“r-x-wxrwx”,然后在此基础上增加SUID和SGID特殊权限,合并后结果是“r-s-wxrwt”。

权限的数字表示法转字符标识法:

3、文件的隐藏属性

Linux系统中的文件除了具备一般权限和特殊权限之外,还有一种隐藏权限,即被隐藏起来的权限,默认情况下不能直接被用户发觉。有用户曾经在生产环境和RHCE考试题目中碰到过明明权限充足但却无法删除某个文件的情况,或者仅能在日志文件中追加内容而不能修改或删除内容,这在一定程度上阻止了黑客篡改系统日志的图谋,因此这种“奇怪”的文件也保障了Linux系统的安全性。

既然叫隐藏权限了,那肯定不能用常规的ls命令就让我们看到它的真面目,专用的设置命令是chattr,专用的查看命令是lsattr

1)chattr命令

chattr命令用于设置文件的隐藏权限,英文全称为:“change attributes”,语法格式为:“chattr [参数] 文件名称”。

如果想要把某个隐藏功能添加到文件上,则需要在命令后面追加“+参数”,如果想要把某个隐藏功能移出文件,则需要追加“-参数”。

chattr命令中的参数及其作用:

参数 作用
i 无法对文件进行修改;若对目录设置了该参数,则仅能修改其中的子文件内容而不能新建或删除文件
a 仅允许补充(追加)内容,无法覆盖/删除内容(Append Only)
S 文件内容在变更后立即同步到硬盘(sync)
s 彻底从硬盘中删除,不可恢复(用0填充原文件所在硬盘区域)
A 不再修改这个文件或目录的最后访问时间(atime)
b 不再修改文件或目录的存取时间
D 检查压缩文件中的错误
d 使用dump命令备份时忽略本文件/目录
c 默认将文件或目录进行压缩
u 当删除该文件后依然保留其在硬盘中的数据,方便日后恢复
t 让文件系统支持尾部合并(tail-merging)
x 可以直接访问压缩文件中的内容

为了让读者能够更好地见识隐藏权限的效果,我们先来创建一个普通文件,然后立即尝试删除(这个操作肯定会成功):

[root@linuxprobe ~]# echo "for Test" > linuxprobe
[root@linuxprobe ~]# rm linuxprobe
rm: remove regular file ‘linuxprobe’? y

实践是检验真理的唯一标准。如果您没有亲眼见证过隐藏权限强大功能的美妙,就一定不会相信原来Linux系统会如此安全。接下来再次新建一个普通文件,并为其设置不允许删除与覆盖(+a参数)权限,然后再尝试将这个文件删除:

[root@linuxprobe ~]# echo "for Test" > linuxprobe
[root@linuxprobe ~]# chattr +a linuxprobe
[root@linuxprobe ~]# rm linuxprobe
rm: remove regular file ‘linuxprobe’? y
rm: cannot remove ‘linuxprobe’: Operation not permitted

可见,上述操作失败了。

2)lsattr命令

lsattr命令用于查看文件的隐藏权限,英文全称为:“list attributes”,语法格式为:“lsattr [参数] 文件名称”。

在Linux系统中,文件的隐藏权限必须使用lsattr命令来查看,平时使用的ls之类的命令则看不出端倪:

[root@linuxprobe ~]# ls -al linuxprobe
-rw-r--r--. 1 root root 9 Feb 12 11:42 linuxprobe

一旦使用lsattr命令后,文件上被赋予的隐藏权限马上就会原形毕露:

[root@linuxprobe ~]# lsattr linuxprobe
-----a---------- linuxprobe

此时按照显示的隐藏权限的类型(字母),使用chattr命令将其去掉:

[root@linuxprobe ~]# chattr -a linuxprobe
[root@linuxprobe ~]# lsattr linuxprobe 
---------------- linuxprobe
[root@linuxprobe ~]# rm linuxprobe 
rm: remove regular file ‘linuxprobe’? y

一般我们会将-a参数设置到日志文件(/var/log/messages)上面,这样在不影响系统正常写入日志的前提下,还可以防止黑客清理自己的作案证据。如果希望彻底的保护起某个文件,不允许任何人修改和删除它的话,不妨加上-i参数试试,效果特别好。

4、文件访问控制列表

不知道大家是否发现,前文讲解的一般权限、特殊权限、隐藏权限其实有一个共性,那就是权限是针对某一类用户设置的,能够对很多人同时生效。如果希望对某个指定的用户进行单独的权限控制,就需要用到文件的访问控制列表(FACL,File Access Control Lists)了。通俗来讲,基于普通文件或目录设置ACL访问控制其实就是针对指定的用户或用户组设置文件或目录的操作权限,更加精准的派发权限。另外,如果针对某个目录设置了ACL,则目录中的文件会继承其权限;若针对文件设置了ACL,则文件不再继承其所在目录的权限。

为了更直观地看到ACL对文件权限控制的强大效果,我们先切换到普通用户,然后尝试进入root管理员的家目录中。在没有针对普通用户对root管理员的家目录设置ACL之前,其执行结果如下所示:

[root@localhost ~]# su - dev1
上一次登录:三 7月 24 22:53:31 CST 2024pts/0 上
[dev1@localhost ~]$ cd /root
-bash: cd: /root: 权限不够
[dev1@localhost ~]$ exit

1)setfacl命令

setfacl命令用于管理文件的ACL权限规则,英文全称为:“set files ACL”,语法格式为:“ setfacl [参数] 文件名称”。

ACL权限提供的是在所有者、所属组、其他人的读/写/执行权限之外的特殊权限控制,使用setfacl命令可以针对单一用户或用户组、单一文件或目录来进行读/写/执行权限的控制。其中,针对目录文件需要使用-R递归参数;针对普通文件则使用-m参数;如果想要删除某个文件的ACL,则可以使用-b参数。

setfacl命令中的参数以及作用:

参数 作用
-m 修改权限
-M 从文件中读取权限
-x 删除某个权限
-b 删除全部权限
-R 递归子目录

例如我们原本是无法进入到/root目录中的,现在给这位普通用户单独设置下权限:

[root@localhost ~]# setfacl -Rm u:dev1:rwx /root

随后再切换到这位普通用户的身份下,就能正常进入:

[root@localhost ~]# su - dev1
上一次登录:四 7月 25 21:37:50 CST 2024pts/0 上
[dev1@localhost ~]$ cd /root
[dev1@localhost root]$ ls
anaconda-ks.cfg  initial-setup-ks.cfg  myfolder  ProgramFiles  公共  模板  视频  图片  文档  下载  音乐  桌面
[dev1@localhost root]$ exit

是不是觉得效果很酷呢?但是现在有这样一个小问题—怎么去查看文件上有哪些ACL呢?常用的ls命令是看不到ACL表信息的,但是却可以看到文件的权限最后一个点(.)变成了加号(+),这就意味着该文件已经设置了ACL。现在大家是不是感觉学得越多,越不敢说自己精通Linux系统了吧?就这么一个不起眼的点(.),竟然还表示这么一种重要的权限。

[root@localhost ~]# ls -ld /root
dr-xrwx---+ 17 root root 4096 7月  25 21:30 /root

2)getfacl命令

getfacl命令用于查看文件的ACL权限规则,英文全称为:“get files ACL”,语法格式为:“ getfacl [参数] 文件名称”。

getfacl命令用于显示文件上设置的ACL信息,格式为“getfacl 文件名称”。Linux系统中的命令就是这么又可爱又好记。想要设置ACL,用的是setfacl命令;要想查看ACL,则用的是getfacl命令。下面使用getfacl命令显示在root管理员家目录上设置的所有ACL信息。

[root@localhost ~]# getfacl /root
getfacl: Removing leading '/' from absolute path names
# file: root
# owner: root
# group: root
user::r-x
user:dev1:rwx
group::r-x
mask::rwx
other::---

ACL权限还可以针对某个用户组来设置,例如允许某个组的用户都可以读写/etc/fstab这个文件:

[root@localhost ~]# setfacl -m g:devgroup1:rw /etc/fstab
[root@localhost ~]# getfacl /etc/fstab
getfacl: Removing leading '/' from absolute path names
# file: etc/fstab
# owner: root
# group: root
user::rw-
group::r--
group:devgroup1:rw-
mask::rw-
other::r--

设置错了想删除?没问题!清空所有ACL权限用-b参数,指定删除某一条权限就用-x参数:

[root@localhost ~]# setfacl -x g:devgroup1 /etc/fstab
[root@localhost ~]# getfacl /etc/fstab
getfacl: Removing leading '/' from absolute path names
# file: etc/fstab
# owner: root
# group: root
user::rw-
group::r--
mask::r--
other::r--

对于ACL权限的设置都是立即且永久生效的,不需要再编辑什么配置文件,这点特别方便~但是也有个安全隐患,如果我们不小心设置错了权限怎么办?就会覆盖掉文件原始的权限信息,并且永远都找不回来了。

温馨提示:操作前备份一下,总是好的习惯。

例如:将 /home 目录上的ACL权限备份一份,要用-R递归参数,这样不仅能够把目录本身的权限备份了,里面的文件权限也都能自动备份。需要注意 getfacl 在备份目录权限时不能使用绝对路径的形式,因此我们需要先切换到最上层根目录,然后再进行操作:

[root@localhost ~]# cd /
[root@localhost /]# getfacl -R home > backup.acl
[root@localhost /]# ls -l
总用量 60
-rw-r--r--.   1 root root 21822 7月  25 21:56 backup.acl

ACL权限的恢复也很简单,使用的是“--restore”参数,由于备份时已经指定了是对home目录进行的操作,所以不需要写对应的目录名称,它能够自动找到要恢复的对象:

[root@localhost /]# setfacl --restore backup.acl

5、su命令与sudo命令

由于为了避免因权限因素导致配置服务失败,从而建议使用root管理员来学习,但是在生产环境中还是要对安全多一份敬畏之心,不要用root管理员去做所有事情。因为一旦执行了错误的命令,可能会直接导致系统崩溃,这样一来,不但客户指责、领导批评,没准奖金也会鸡飞蛋打。但转头一想,尽管Linux系统为了安全性考虑,使得许多系统命令和服务只能被root管理员来使用,但是这也让普通用户受到了更多的权限束缚,从而导致无法顺利完成特定的工作任务。

su命令可以解决切换用户身份的需求,使得当前用户在不退出登录的情况下,顺畅地切换到其他用户,比如从root管理员切换至普通用户:

[root@localhost ~]# su - dev1
上一次登录:四 7月 25 21:40:57 CST 2024pts/0 上
[dev1@localhost ~]$ id
uid=1001(dev1) gid=1001(devgroup1) 组=1001(devgroup1),1003(devgroup3) 环境=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

细心的读者一定会发现,上面的su命令与用户名之间有一个减号(-),这意味着完全切换到新的用户,即把环境变量信息也变更为新用户的相应信息,而不是保留原始的信息。强烈建议在切换用户身份时添加这个减号(-)

另外,当从root管理员切换到普通用户时是不需要密码验证的,而从普通用户切换成root管理员就需要进行密码验证了;这也是一个必要的安全检查:

[dev1@localhost ~]$ su - root
密码:此处输入管理员密码
上一次登录:四 7月 25 21:30:37 CST 2024从 192.168.110.1pts/0

尽管像上面这样使用su命令后,普通用户可以完全切换到root管理员身份来完成相应工作,但这将暴露root管理员的密码,从而增大了系统密码被黑客获取的几率,这并不是最安全的方案。

接下来将介绍如何使用sudo命令把特定命令的执行权限赋予给指定用户,这样既可保证普通用户能够完成特定的工作,也可以避免泄露root管理员密码。我们要做的就是合理配置sudo服务,以便兼顾系统的安全性和用户的便捷性。

温馨提示:

授权原则:在保证普通用户完成相应工作的前提下,尽可能少的赋予额外的权限。

sudo命令用于给普通用户提供额外的权限,语法格式为:“ sudo [参数] 用户名”。

使用sudo命令可以给普通用户提供额外的权限来完成原本只有root管理员才能完成的任务。可以限制用户执行指定的命令、记录用户执行过的每一条命令、集中的管理用户与权限(/etc/sudoers)以及验证密码后一段时间内免验证的方便措施。

sudo命令中的常用参数以及作用:

参数 作用
-h 列出帮助信息
-l 列出当前用户可执行的命令
-u 用户名或UID值 以指定的用户身份执行命令
-k 清空密码的有效时间,下次执行sudo时需要再次进行密码验证
-b 在后台执行指定的命令
-p 更改询问密码的提示语

当然,如果担心直接修改配置文件会出现问题,则可以使用sudo命令提供的visudo命令来配置用户权限。

visudo命令用于编辑配置用户sudo权限文件,语法格式为:“ visudo [参数]”。

这是一条会自动调用vi编辑器来配置/etc/sudoers权限文件的命令,能够解决多个用户同时修改权限而导致的冲突问题,不仅如此,visudo命令还可以对配置文件内的参数进行语法检查,在发现参数错误时进行报错提醒,比用户直接修改文件更友好、安全、方便。

>>> /etc/sudoers: syntax error near line 1 <<<
What now? 
Options are:
(e)dit sudoers file again
e(x)it without saving changes to sudoers file
(Q)uit and save changes to sudoers file (DANGER!)

使用visudo命令配置权限文件时,其操作方法与Vim编辑器中用到的方法完全一致,因此在编写完成后记得在末行模式下保存并退出。配置权限文件时,按照下面的格式将第101行(大约)填写上指定的信息:

谁可以使用 允许使用的主机=(以谁的身份) 可执行命令的列表

  • 谁可以使用:稍后要为那位用户进行命令授权。
  • 允许使用的主机:可以填写ALL代表不限制来源主机,亦可填写如192.168.10.0/24的网段限制来源地址,只有从允许网段登录时才能使用sudo命令。
  • 以谁的身份:可以填写ALL代表系统最高权限,也可以是另外一位用户的名字。
  • 可执行命令的列表:可以填写ALL代表不限制命令的列表,亦可填写如/usr/bin/cat的文件名称来限制命令列表,多个命令文件之间用逗号(,)间隔。

在Linux系统中配置服务文件时,虽然没有硬性规定,但从经验来讲新增的参数位置不建议太靠上,避免服务一些必要的功能没加载完成时,我们填写的新参数不被执行成功。一般会在配置文件中找一下相似的参数,然后在相邻位置进行新的修改,或者选择文件的中下部位置。

[root@localhost ~]# visudo
省略...
     99 ## Allow root to run any commands anywhere
    100 root    ALL=(ALL)       ALL
    101 dev2 ALL=(ALL) ALL
    102
    103 ## Allows members of the 'sys' group to run networking, software,
省略...

在填写完毕后记得要先保存再退出,然后切换至指定的普通用户身份,此时就可以用sudo -l命令查看到所有可执行的命令了(下面的命令中,验证的是该普通用户的密码,而不是root管理员的密码,请读者不要搞混了):

[root@localhost ~]# su - dev2
上一次登录:一 7月 22 21:54:09 CST 2024pts/0 上
[dev2@localhost ~]$ sudo -l

我们信任您已经从系统管理员那里了解了日常注意事项。
总结起来无外乎这三点:

    #1) 尊重别人的隐私。
    #2) 输入前要先考虑(后果和风险)。
    #3) 权力越大,责任越大。

[sudo] dev2 的密码:此处输入dev2用户的密码
匹配 %2$s 上 %1$s 的默认条目:
    !visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin, env_reset, 
env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS", env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE", env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY", secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin 用户 dev2 可以在 localhost 上运行以下命令: (ALL) ALL

接下来是见证奇迹的时刻!作为一名普通用户,是肯定不能看到root管理员的家目录(/root)中的文件信息的,但是,只需要在想执行的命令前面加上sudo命令就行了:

[root@localhost ~]# su - dev2
上一次登录:四 7月 25 23:35:47 CST 2024pts/0 上
[dev2@localhost ~]$ ls /root
ls: 无法打开目录/root: 权限不够
[dev2@localhost ~]$ sudo ls /root
[sudo] dev2 的密码:
anaconda-ks.cfg  initial-setup-ks.cfg  myfolder  ProgramFiles  公共  模板  视频  图片  文档  下载  音乐  桌面
[dev2@localhost ~]$ sudo ls /root
anaconda-ks.cfg  initial-setup-ks.cfg  myfolder  ProgramFiles  公共  模板  视频  图片  文档  下载  音乐  桌面

效果立竿见影!但是考虑到生产环境中不允许某个普通用户拥有整个系统中所有命令的最高执行权(这也不符合前文提到的权限赋予原则,即尽可能少地赋予权限),因此ALL参数就有些不合适了。因此只能赋予普通用户具体的命令以满足工作需求,这也受到了必要的权限约束。如果需要让某个用户只能使用root管理员的身份执行指定的命令,切记一定要给出该命令的绝对路径,否则系统会识别不出来,这时可以先使用whereis命令找出命令所对应的保存路径

[dev2@localhost ~]$ exit
登出
[root@localhost ~]# whereis cat
cat: /usr/bin/cat /usr/share/man/man1/cat.1.gz /usr/share/man/man1p/cat.1p.gz
[root@localhost ~]# whereis reboot
reboot: /usr/sbin/reboot /usr/share/man/man2/reboot.2.gz /usr/share/man/man8/reboot.8.gz

然后使用visudo命令继续编辑权限文件,将原先101行所新增的参数作如下修改,多个命令之间用英文逗号(,)分隔。

[root@localhost ~]# visudo
省略...
     99 ## Allow root to run any commands anywhere
    100 root    ALL=(ALL)       ALL
    101 dev2 ALL=(ALL) /usr/bin/cat,/usr/sbin/reboot
    102
    103 ## Allows members of the 'sys' group to run networking, software,
省略...

在编辑好后依然是先保存再退出。再次切换到指定的普通用户,然后尝试正常查看某个系统文件的内容,此时系统提示没有权限(Permission denied)。再使用sudo命令就能顺利地查看文件内容了:

[root@localhost ~]# su - dev2
上一次登录:五 7月 26 23:21:09 CST 2024pts/0 上
[dev2@localhost ~]$ cat /etc/shadow
cat: /etc/shadow: 权限不够
[dev2@localhost ~]$ sudo cat /etc/shadow
[sudo] dev2 的密码:此处输入dev2用户的密码
root:$6$FZjns6bztDTKQTKq$qJuaQ5KdExQzIznFeCSJHDXkeSN9vS3u8G/kw6HhLuZb91kftob6IhgSo.iqqlEgdBd8Oov3M2OKclNXvBuSQ0::0:99999:7:::
bin:*:18353:0:99999:7:::
daemon:*:18353:0:99999:7:::
adm:*:18353:0:99999:7:::
lp:*:18353:0:99999:7:::
sync:*:18353:0:99999:7:::
shutdown:*:18353:0:99999:7:::
halt:*:18353:0:99999:7:::
省略...
[dev2@localhost ~]$ exit
登出

不知大家是否发觉在每次执行sudo命令后都会要求验证一下密码。虽然这个密码就是当前登录用户的密码,但是每次执行sudo命令都要输入一次密码其实也挺麻烦的,这时可以添加NOPASSWD参数,使得用户下次再执行sudo命令时就不用密码验证啦~

[root@localhost ~]# visudo
省略...
     99 ## Allow root to run any commands anywhere
    100 root    ALL=(ALL)       ALL
    101 dev2 ALL=(ALL) NOPASSWD:/usr/bin/cat,/usr/sbin/reboot
    102
    103 ## Allows members of the 'sys' group to run networking, software,
省略...

这样,当切换到普通用户后再执行命令时,就不用再频繁地验证密码了,我们在日常工作中也就痛快至极了。

[root@localhost ~]# su - dev2
上一次登录:五 7月 26 23:48:06 CST 2024pts/0 上
[dev2@localhost ~]$ reboot
User root is logged in on sshd.
User root is logged in on sshd.
Please retry operation after closing inhibitors and logging out other users.
Alternatively, ignore inhibitors and users with 'systemctl reboot -i'.
[dev2@localhost ~]$ sudo reboot

请细心留意上面的用户身份变换,visudo命令只有root管理员才可以执行,普通用户使用会提示权限不足。

五、组和权限设定的命令

该点其实上文已经提到过了,就是 chown 和 chmod 这2个命令。

1、chmod命令

chmod命令用于设置文件的一般权限及特殊权限,英文全称为:“change mode”,语法格式为:“chmod [参数] 文件名”。

这是一个与日常设置文件权限强相关的命令,例如要把一个文件的权限设置成其所有者可读可写可执行、所属组可读可写、其他人没有任何权限,则相应的字符法表示为rwxrw----,其对应的数字法表示为760。

[root@linuxprobe ~]# ls -l anaconda-ks.cfg 
-rw-------. 1 root root 1407 Jul 21 05:09 anaconda-ks.cfg
[root@linuxprobe ~]# chmod 760 anaconda-ks.cfg 
[root@linuxprobe ~]# ls -l anaconda-ks.cfg 
-rwxrw----. 1 root root 1407 Jul 21 05:09 anaconda-ks.cfg

2、chown命令

chown命令用于设置文件的所有者和所有组,英文全称为:“change own”,语法格式为:“chown 所有者:所有组 文件名”。

chmod和chown命令是用于修改文件属性和权限的最常用命令,它们还有一个特别的共性,就是针对目录进行操作时需要加上大写参数-R来表示递归操作,即对目录内所有的文件进行整体操作。

使用“所有者:所有组”的格式轻松把刚刚那个文件的所属信息修改一下,变更后的效果如下:

[root@linuxprobe ~]# chown linuxprobe:linuxprobe anaconda-ks.cfg 
[root@linuxprobe ~]# ls -l anaconda-ks.cfg 
-rwxrw----. 1 linuxprobe linuxprobe 1407 Jul 21 05:09 anaconda-ks.cfg

 

此文由博主精心撰写转载请保留此原文链接:https://www.cnblogs.com/xyh9039/p/18300859

版权声明:如有雷同纯属巧合,如有侵权请及时联系本人修改,谢谢!!! 

posted @ 2024-07-27 00:13  谢友海  阅读(176)  评论(0编辑  收藏  举报