Linux系统中的文件除了具备一般权限和特殊权限之外,还有一种隐藏权限,即被隐藏起来的权限,默认情况下不能直接被用户发觉。明明权限充足但却无法删除某个文件的情况,或者仅能在日志文件中追加内容而不能修改或删除内容,这在一定程度上阻止了黑客篡改系统日志的图谋。
1. chattr命令
chattr命令用于设置文件的隐藏权限,格式为“chattr [参数] 文件”。如果想要把某个隐藏功能添加到文件上,则需要在命令后面追加“+参数”,如果想要把某个隐藏功能移出文件,则需要追加“-参数”。chattr命令中可供选择的隐藏权限参数非常丰富。
chattr命令中用于隐藏权限的参数及其作用
参数 | 作用 |
i | 无法对文件进行修改;若对目录设置了该参数,则仅能修改其中的子文件内容而不能新建或删除文件 |
a | 仅允许补充(追加)内容,无法覆盖/删除内容(Append Only) |
S | 文件内容在变更后立即同步到硬盘(sync) |
s | 彻底从硬盘中删除,不可恢复(用0填充原文件所在硬盘区域) |
A | 不再修改这个文件或目录的最后访问时间(atime) |
b | 不再修改文件或目录的存取时间 |
D | 检查压缩文件中的错误 |
d | 使用dump命令备份时忽略本文件/目录 |
c | 默认将文件或目录进行压缩 |
u | 当删除该文件后依然保留其在硬盘中的数据,方便日后恢复 |
t | 让文件系统支持尾部合并(tail-merging) |
x | 可以直接访问压缩文件中的内容 |
先来创建一个普通文件,然后立即尝试删除(这个操作肯定会成功):
[root@hushenjian ~]# echo "for Test" > linuxprobe [root@hushenjian ~]# rm linuxprobe rm: remove regular file ‘linuxprobe’? y
接下来我们再次新建一个普通文件,并为其设置不允许删除与覆盖(+a参数)权限,然后再尝试将这个文件删除:
[root@hushenjian ~]# echo "for Test" > linuxprobe [root@hushenjian ~]# chattr +a linuxprobe [root@hushenjian ~]# rm linuxprobe rm: remove regular file ‘linuxprobe’? y rm: cannot remove ‘linuxprobe’: Operation not permitted
2. lsattr命令
lsattr命令用于显示文件的隐藏权限,格式为“lsattr [参数] 文件”。在Linux系统中,文件的隐藏权限必须使用lsattr命令来查看,平时使用的ls之类的命令则看不出端倪:
[root@hushenjian ~]# ls -al linuxprobe -rw-r--r--. 1 root root 9 Feb 12 11:42 linuxprobe
一旦使用lsattr命令后,文件上被赋予的隐藏权限马上就会原形毕露。此时可以按照显示的隐藏权限的类型(字母),使用chattr命令将其去掉:
[root@hushenjian ~]# lsattr linuxprobe -----a---------- linuxprobe [root@hushenjian ~]# chattr -a linuxprobe [root@hushenjian ~]# lsattr linuxprobe ---------------- linuxprobe [root@hushenjian ~]# rm linuxprobe rm: remove regular file ‘linuxprobe’? y
一般权限、特殊权限、隐藏权限其实有一个共性—权限是针对某一类用户设置的。如果希望对某个指定的用户进行单独的权限控制,就需要用到文件的访问控制列表(ACL)了。通俗来讲,基于普通文件或目录设置ACL其实就是针对指定的用户或用户组设置文件或目录的操作权限。另外,如果针对某个目录设置了ACL,则目录中的文件会继承其ACL;若针对文件设置了ACL,则文件不再继承其所在目录的ACL。
为了更直观地看到ACL对文件权限控制的强大效果,我们先切换到普通用户,然后尝试进入root管理员的家目录中。在没有针对普通用户对root管理员的家目录设置ACL之前,其执行结果如下所示:
[root@hushenjian ~]# su - linuxprobe Last login: Sat Mar 21 16:31:19 CST 2017 on pts/0 [hushenjian@huhsenjian ~]$ cd /root -bash: cd: /root: Permission denied [hushenjian@hushenjian root]$ exit
1. setfacl命令
setfacl命令用于管理文件的ACL规则,格式为“setfacl [参数] 文件名称”。文件的ACL提供的是在所有者、所属组、其他人的读/写/执行权限之外的特殊权限控制,使用setfacl命令可以针对单一用户或用户组、单一文件或目录来进行读/写/执行权限的控制。其中,针对目录文件需要使用-R递归参数;针对普通文件则使用-m参数;如果想要删除某个文件的ACL,则可以使用-b参数。下面来设置用户在/root目录上的权限:
[root@hushenjian ~]# setfacl -Rm u:linuxprobe:rwx /root [root@hushenjian ~]# su - linuxprobe Last login: Sat Mar 21 15:45:03 CST 2017 on pts/1 [hushenjain@hushenjian ~]$ cd /root [hushenjian@hushenjian root]$ ls anaconda-ks.cfg Downloads Pictures Public [hushenjian@hushenjian root]$ cat anaconda-ks.cfg [hushenjain@hushenjian root]$ exit
怎么去查看文件上有那些ACL呢?常用的ls命令是看不到ACL表信息的,但是却可以看到文件的权限最后一个点(.)变成了加号(+),这就意味着该文件已经设置了ACL了。
[root@hushenjian ~]# ls -ld /root dr-xrwx---+ 14 root root 4096 May 4 2017 /root
2. getfacl命令
getfacl命令用于显示文件上设置的ACL信息,格式为“getfacl 文件名称”。想要设置ACL,用的是setfacl命令;要想查看ACL,则用的是getfacl命令。下面使用getfacl命令显示在root管理员家目录上设置的所有ACL信息。
[root@linuxprobe ~]# getfacl /root getfacl: Removing leading '/' from absolute path names # file: root # owner: root # group: root user::r-x user:linuxprobe:rwx group::r-x mask::rwx other::---
sudo命令用于给普通用户提供额外的权限来完成原本root管理员才能完成的任务,格式为“sudo [参数] 命令名称”。sudo服务中可用的参数以及相应的作用如表5-7所示。
sudo服务中的可用参数以及作用
参数 | 作用 |
-h | 列出帮助信息 |
-l | 列出当前用户可执行的命令 |
-u 用户名或UID值 | 以指定的用户身份执行命令 |
-k | 清空密码的有效时间,下次执行sudo时需要再次进行密码验证 |
-b | 在后台执行指定的命令 |
-p | 更改询问密码的提示语 |
sudo命令具有如下功能:
限制用户执行指定的命令:
记录用户执行的每一条命令;
配置文件(/etc/sudoers)提供集中的用户管理、权限与主机等参数;
验证密码的后5分钟内(默认值)无须再让用户再次验证密码。
当然,如果担心直接修改配置文件会出现问题,则可以使用sudo命令提供的visudo命令来配置用户权限。这条命令在配置用户权限时将禁止多个用户同时修改sudoers配置文件,还可以对配置文件内的参数进行语法检查,并在发现参数错误时进行报错。
只有root管理员才可以使用visudo命令编辑sudo服务的配置文件。
visudo: >>> /etc/sudoers: syntax error near line 111 <<< What now? Options are: (e)dit sudoers file again (x)it without saving changes to sudoers file (Q)uit and save changes to sudoers file (DANGER!)
使用visudo命令配置sudo命令的配置文件时,在sudo命令的配置文件中,按照下面的格式将第99行(大约)填写上指定的信息:
谁可以使用 允许使用的主机=(以谁的身份) 可执行命令的列表
[root@linuxprobe ~]# visudo 96 ## 97 ## Allow root to run any commands anywhere 98 root ALL=(ALL) ALL 99 linuxprobe ALL=(ALL) ALL
在填写完毕后记得要先保存再退出,然后切换至指定的普通用户身份,用sudo -l命令查看到所有可执行的命令了(下面的命令中,验证的是该普通用户的密码,而不是root管理员的密码):
[root@hushenjian ~]# su - linuxprobe Last login: Thu Sep 3 15:12:57 CST 2017 on pts/1 [hushenjian@hushenjian ~]$ sudo -l [sudo] password for linuxprobe:此处输入linuxprobe用户的密码 Matching Defaults entries for linuxprobe on this host: requiretty, !visiblepw, always_set_home, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC 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 User linuxprobe may run the following commands on this host: (ALL) ALL
接下来,作为一名普通用户,是肯定不能看到root管理员的/root中的文件信息的,但是,只需要在想执行的命令前面加上sudo命令就可以了:
[hushenjian@hushenjian ~]$ ls /root ls: cannot open directory /root: Permission denied [hushenjian@hushenjian ~]$ sudo ls /root anaconda-ks.cfg Documents initial-setup-ks.cfg Pictures Templates Desktop Downloads Music Public Videos
但是考虑到生产环境中不允许某个普通用户拥有整个系统中所有命令的最高执行权,因此ALL参数有些不合适。如果需要让某个用户只能使用root管理员的身份执行指定的命令,切记一定要给出该命令的绝对路径,可以先使用whereis命令找出命令所对应的保存路径,然后把配置文件第99行的用户权限参数修改成对应的路径即可:
[hushenjian@hushenjian ~]$ exit logout [root@hushenjian ~]# whereis cat cat: /usr/bin/cat /usr/share/man/man1/cat.1.gz /usr/share/man/man1p/cat.1p.gz [root@hushenajian ~]# visudo 96 ## 97 ## Allow root to run any commands anywhere 98 root ALL=(ALL) ALL 99 linuxprobe ALL=(ALL) /usr/bin/cat
再次切换到指定的普通用户,然后尝试正常查看某个文件的内容,此时系统提示没有权限。这时再使用sudo命令就可以顺利地查看文件内容了:
[root@linuxprobe ~]# su - linuxprobe Last login: Thu Sep 3 15:51:01 CST 2017 on pts/1 [linuxprobe@linuxprobe ~]$ cat /etc/shadow cat: /etc/shadow: Permission denied [linuxprobe@linuxprobe ~]$ sudo cat /etc/shadow root:$6$GV3UVtX4ZGg6ygA6$J9pBuPGUSgZslj83jyoI7ThJla9ZAULku3BcncAYF00Uwk6Sqc4E36MnD1hLtlG9QadCpQCNVJs/5awHd0/pi1:16626:0:99999:7::: bin:*:16141:0:99999:7::: daemon:*:16141:0:99999:7::: adm:*:16141:0:99999:7::: lp:*:16141:0:99999:7::: sync:*:16141:0:99999:7::: shutdown:*:16141:0:99999:7::: halt:*:16141:0:99999:7::: mail:*:16141:0:99999:7::: operator:*:16141:0:99999:7::: games:*:16141:0:99999:7::: ftp:*:16141:0:99999:7::: nobody:*:16141:0:99999:7::: ………………省略部分文件内容………………
每次执行sudo命令后都会要求验证一下密码。可以添加NOPASSWD参数,使得用户执行sudo命令时不再需要密码验证:
[hushenjian@hushenjian ~]$ exit logout [root@hushenjian ~]# whereis poweroff poweroff: /usr/sbin/poweroff /usr/share/man/man8/poweroff.8.gz [root@hushenjian ~]# visudo 96 ## 97 ## Allow root to run any commands anywhere 98 root ALL=(ALL) ALL 99 linuxprobe ALL=NOPASSWD: /usr/sbin/poweroff
当切换到普通用户后再执行命令时,不用再频繁地验证密码。
[root@hushenjian ~]# su - hushenjian Last login: Thu Sep 3 15:58:31 CST 2017 on pts/1 [hushenjian@hushenjian ~]$ poweroff User root is logged in on seat0. Please retry operation after closing inhibitors and logging out other users. Alternatively, ignore inhibitors and users with 'systemctl poweroff -i'. [hushenjian@hushenjian ~]$ sudo poweroff