9. Linux权限管理(2)

目录

9.11 Linux SetUID(SUID)特殊权限

9.12 不要轻易设置SetUID(SUID)权限,否则会带来重大安全隐患!

9.13 Linux SetGID(SGID)特殊权限

SetGID(SGID)对文件的作用

SetGID(SGID)对目录的作用

9.14 Linux Stick BIT(SBIT)特殊权限

9.15 Linux文件特殊权限(SUID、SGID和SBIT)的设置

9.16 Linux修改文件或目录的隐藏属性(chattr命令)

9.17 Linux查看文件或目录的隐藏属性(lsattr命令)

9.18 Linux sudo命令(包含和su命令的对比)

sudo命令的配置文件/etc/sudoers

9.19 结合实例分析Linux权限对指令执行的影响


9.11 Linux SetUID(SUID)特殊权限

 

在讲解《权限位》一节时提到过,其实除了 rwx 权限,还会用到 s 权限,例如:

[root@localhost ~]# ls -l /usr/bin/passwd
-rwsr-xr-x. 1 root root 22984 Jan  7  2007 /usr/bin/passwd

可以看到,原本表示文件所有者权限中的 x 权限位,却出现了 s 权限,此种权限通常称为 SetUID,简称 SUID 特殊权限。

SUID 特殊权限仅适用于可执行文件,所具有的功能是,只要用户对设有 SUID 的文件有执行权限,那么当用户执行此文件时,会以文件所有者的身份去执行此文件,一旦文件执行结束,身份的切换也随之消失。

举一个例子,我们都知道,Linux 系统中所有用户的密码数据都记录在 /etc/shadow 这个文件中,通过 ll /etc/shadow 命令可以看到,此文件的权限是 0(---------),也就是说,普通用户对此文件没有任何操作权限。

这就会产生一个问题,为什么普通用户可以使用 passwd 命令修改自己的密码呢?

本节开头已经显示了 passwd 命令的权限配置,可以看到,此命令拥有 SUID 特殊权限,而且其他人对此文件也有执行权限,这就意味着,任何一个用户都可以用文件所有者,也就是 root 的身份去执行 passwd 命令。

Linux 系统中,绝对多数命令的文件所有者默认都是 root。

换句话说,当普通用户使用 passwd 命令尝试更改自己的密码时,实际上是在以 root 的身份执行passwd命令,正因为 root 可以将密码写入 /etc/shadow 文件,所以普通用户也能做到。只不过,一旦命令执行完成,普通用户所具有的 root身份也随之消失。

如果我们手动将 /usr/bin/passwd 文件的 SUID 权限取消,会发生什么呢?观察如下命令的执行过程:

[root@localhost ~]# chmod u-s /usr/bin/passwd
#属主取消SetUID权限
[root@localhost ~]# ll /usr/bin/passwd
-rwxr-xr-x. 1 root root 30768 Feb 22 2012 /usr/bin/passwd
[root@localhost ~]# su - lamp
[lamp@localhost ~]$ passwd

Changing password for user lamp.
Changing password for user.
(current) UNIX password:
#看起来没有什么问题
New passwor:
Retype new password:
password:Authentication token manipulation error  <--鉴定令牌操作错误
#最后密码没有生效

显然,虽然用户有执行 passwd 命令的权限,但无修改 /etc/shadow 文件的权限,因此最终密码修改失败。

注意,实验完成后,一定要再把 /usr/bin/passwd 文件的 SetUID 权限加上。

那么,普通用户可以使用 cat 命令查看 /etc/shadow 文件吗?答案的否定的,因为 cat 不具有 SUID 权限,因此普通用户在执行 cat /etc/shadow 命令时,无法以  root 的身份,只能以普通用户的身份,因此无法成功读取。

我们可以使用下面这张图来描述上述过程:


9. Linux权限管理(2)_第1张图片
图 1 SUID示意图


由此,我们可以总结出,SUID 特殊权限具有如下特点:

  • 只有可执行文件才能设定 SetUID 权限,对目录设定 SUID,是无效的。
  • 用户要对该文件拥有 x(执行)权限。
  • 用户在执行该文件时,会以文件所有者的身份执行。
  • SetUID 权限只在文件执行过程中有效,一旦执行完毕,身份的切换也随之消失。

 

9.12 不要轻易设置SetUID(SUID)权限,否则会带来重大安全隐患!

 

SetUID权限设置不当,会给 Linux 系统造成重大安全隐患。

前面的例子中,我们试验了将 passwd 命令取消 SUID 权限,这会导致 passwd 命令的功能失效。那么,如果我们手动给默认无 SetUID 权限的系统命令赋予 SetUID 权限,会出现什么情况呢?

比如说,我们尝试给 Vim 赋予 SetUID 权限:

[root@localhost ~]# chmod u+s /usr/bin/vim
[root@localhost ~]# ll /usr/bin/vim

-rwsr-xr-x. 1 root root 1847752 Apr 5 2012 /usr/bin/vim

此时你会发现,即便是普通用户使用 vim 命令,都会暂时获得 root 的身份和权限,例如,很多原本普通用户不能查看和修改的文件,竟然可以查看了,以 /etc/passwd 和 /etc/shadow 文件为例,普通用户也可以将自己的 UID 手动修改为 0,这意味着,此用户升级成为了超级用户。除此之外,普通用户还可以修改例如 /etc/inittab 和 /etc/fstab 这样重要的系统文件,可以轻易地使系统瘫痪。

其实,任何只有管理员可以执行的命令,如果被赋予了 SetUID 权限,那么后果都是灾难性的。普通用户可以随时重启服务器、随时关闭看得不顺眼的服务、随时添加其他普通用户的服务器,可以想象是什么样子。所以,SetUID 权限不能随便设置。

有读者可能会问,如何防止他人(例如黑客)对 SetUID 权限的恶意篡改呢?这里,给大家提供以下几点建议:

  1. 关键目录要严格控制写权限,比如 "/"、"/usr" 等。
  2. 用户的密码设置要严格遵守密码规范。
  3. 对系统中默认应该有 SetUID 权限的文件制作一张列表,定时检査有没有列表之外的文件被设置了 SetUID 权限。


前面 2 点不再做过多解释,这里就最后一点,给大家提供一个脚本,仅供参考。

首先,在服务器第一次安装完成后,马上查找系统中所有拥有 SetUID 和 SetGID 权限的文件,把它们记录下来,作为扫描的参考模板。如果某次扫描的结果和本次保存下来的模板不一致,就说明有文件被修改了 SetUID 和 SetGID 权限。命令如下:

[root@localhost ~]# find / -perm -4000 -o -perm -2000 > /root/suid.list
#-perm安装权限査找。-4000对应的是SetUID权限,-2000对应的是SetGID权限
#-o是逻辑或"or"的意思。并把命令搜索的结果放在/root/suid.list文件中
接下来,只要定时扫描系统,然后和模板文件比对就可以了。脚本如下:
[root@localhost ~]#vi suidcheck.sh
#!/bin/bash
find / -perm -4000 -o -perm -2000 > /tmp/setuid.check
#搜索系统中所有拥有SetUID和SetGID权限的文件,并保存到临时目录中
for i in $(cat /tmp/setuid.check)
#循环,每次循环都取出临时文件中的文件名
do
    grep $i /root/suid.list > /dev/null
    #比对这个文件名是否在模板文件中
    if ["$?"!="o"]
    #检测测上一条命令的返回值,如果不为0,则证明上一条命令报错
    then
        echo "$i isn't in listfile! " >>/root/suid_log_$(date +%F)
        #如果文件名不在模板文件中,则输出错误信息,并把报错写入日志中
    fi
done
rm -rf/tmp/setuid.check
#删除临时文件

[root@localhost ~]# chmod u+s /bin/vi
#手工给vi加入SetUID权限
[root@localhost ~]# ./suidcheck.sh
#执行检测脚本
[root@localhost ~]# cat suid_log_2013-01-20
/bin/vi isn't in listfile!
#报错了,vi不在模板文件中。代表vi被修改了SetUID权限

这个脚本成功的关键在于模板文件是否正常。所以一定要安装完系统就马上建立模板文件,并保证模板文件的安全。

注意,除非特殊情况,否则不要手工修改 SetUID 和 SetGID 权限,这样做非常不安全。而且就算我们做实验修改了 SetUID 和 SetGID 权限,也要马上修改回来,以免造成安全隐患。

SetGID 特殊权限的相关内容,下节会做详细介绍。

 

9.13 Linux SetGID(SGID)特殊权限

 

前面学习了 SetUID,那么,什么是 SetGID 呢?很简单,当 s 权限位于所属组的 x 权限位时,就被称为 SetGID,简称 SGID 特殊权限。例如:

[root@localhost ~]# ll /usr/bin/locate
-rwx--s--x. 1 root slocate 35612 8月24 2010 /usr/bin/locate

与 SUID 不同的是,SGID 既可以对文件进行配置,也可以对目录进行配置。

SetGID(SGID)对文件的作用

同 SUID 类似,对于文件来说,SGID 具有如下几个特点:

  • SGID 只针对可执行文件有效,换句话说,只有可执行文件才可以被赋予 SGID 权限,普通文件赋予 SGID 没有意义。
  • 用户需要对此可执行文件有 x 权限;
  • 用户在执行具有 SGID 权限的可执行文件时,用户的群组身份会变为文件所属群组;
  • SGID 权限赋予用户改变组身份的效果,只在可执行文件运行过程中有效;

其实,SGID 和 SUID 的不同之处就在于,SUID 赋予用户的是文件所有者的权限,而 SGID 赋予用户的是文件所属组的权限,就这么简单。

就以本节开头的 locate 命令为例,可以看到,/usr/bin/locate 文件被赋予了 SGID 的特殊权限,这就意味着,当普通用户使用 locate 命令时,该用户的所属组会直接变为 locate 命令的所属组,也就是 slocate。

我们知道,locate 命令是用于在系统中按照文件名查找符合条件的文件的,当执行搜索操作时,它会通过搜索 /var/lib/mlocate/mlocate.db 这个数据库中的数据找到答案,我们来看看此数据库的权限:

[root@localhost ~]# ll /var/lib/mlocate/mlocate.db
-rw-r-----. 1 root slocate 1838850 1月20 04:29 /var/lib/mlocate/mlocate.db

可以看到,mlocate.db 文件的所属组为 slocate,虽然对文件只拥有 r 权限,但对于普通用户执行 locate 命令来说,已经足够了。一方面,普通用户对 locate命令拥有执行权限,其次,locate 命令拥有 SGID 权限,这使得普通用户在执行 locate 命令时,所属组身份会变为 slocate,而 slocate 对 mlocate.db 数据库文件拥有 r 权限,所以即便是普通用户,也可以成功执行 locate 命令。

再次强调,无论是 SUID,还是 SGID,它们对用户身份的转换,只有在命令执行的过程中有效,一旦命令执行完毕,身份转换也随之失效。

SetGID(SGID)对目录的作用

事实上,SGID 也能作用于目录,且这种用法很常见。

当一个目录被赋予 SGID 权限后,进入此目录的普通用户,其有效群组会变为该目录的所属组,会就使得用户在创建文件(或目录)时,该文件(或目录)的所属组将不再是用户的所属组,而使用的是目录的所属组。

也就是说,只有当普通用户对具有 SGID 权限的目录有 rwx 权限时,SGID 的功能才能完全发挥。比如说,如果用户对该目录仅有 rx 权限,则用户进入此目录后,虽然其有效群组变为此目录的所属组,但由于没有 x 权限,用户无法在目录中创建文件或目录,SGID 权限也就无法发挥它的作用。

举个例子:

[root@localhost ~]# cd /tmp
#进入临时目录做此实验。因为只有临时目录才允许普通用户修改
[root@localhost tmp]# mkdir dtest
#建立测试目录
[root@localhost tmp]# chmod g+s dtest
#给测试目录赋予SetGID权限
[root@localhost tmp]# ll -d dtest
drwxr-sr-x 2 root root 4096 Apr 19 06:04 dtest
#SetGID权限已经生效
[root@localhost tmp]# chmod 777 dtest
#给测试目录赋予777权限,让普通用户可以写
[root@localhost tmp]# su - lamp
[lamp@localhost ~]# grep lamp /etc/passwd /etc/group
/etc/passwd:lamp:x:501:501::/home/lamp:/bin/bash
/etc/group:lamp:x:501:
#切换成普通用户lamp,此用户的所属群组为 lamp
[lamp@localhost ~]$ cd /tmp/dtest/
#普通用户进入测试目录
[lamp@localhost dtest]$ touch abc
[lamp@localhost dtest]$ mkdir zimulu

#在此目录中创建新的文件 abc 和子目录 zimulu
[lamp@localhost dtest]$ ll
total 0
-rw-rw-r--. 1 lamp root 0 Apr 19 06:07 abc
drwxrwsr-x. 2 lamp root 40 Apr 19 06:07 zimulu

可以看到,虽然是 lamp 用户创建的 abc 文件和 zimulu 目录,但它们的所属组都不是 lamp(lamp 用户的所属组),而是 root(dtest 目录的所属组)。

 

9.14 Linux Stick BIT(SBIT)特殊权限

 

Sticky BIT,简称 SBIT 特殊权限,可意为粘着位、粘滞位、防删除位等。

SBIT 权限仅对目录有效,一旦目录设定了 SBIT 权限,则用户在此目录下创建的文件或目录,就只有自己和 root 才有权利修改或删除该文件。

也就是说,当甲用户以目录所属组或其他人的身份进入 A 目录时,如果甲对该目录有 w 权限,则表示对于 A 目录中任何用户创建的文件或子目录,甲都可以进行修改甚至删除等操作。但是,如果 A 目录设定有 SBIT 权限,那就大不一样啦,甲用户只能操作自己创建的文件或目录,而无法修改甚至删除其他用户创建的文件或目录。

举个例子,Linux 系统中,存储临时文件的 /tmp 目录就设定有 SBIT 权限:

[root@localhost ~]# ll -d /tmp
drwxrwxrwt. 4 root root 4096 Apr 19 06:17 /tmp

可以看到,在其他人身份的权限设定中,原来的 x 权限位被 t 权限占用了,这就表示此目录拥有 SBIT 权限。通过下面一系列的命令操作,我们来具体看看 SBIT 权限对 /tmp 目录的作用。

[root@localhost ~]# useradd lamp
[root@localhost ~]# useradd lamp1

#建立测试用户lamp和lamp1,省略设置密码过程
[root@localhost ~]# su -lamp
#切换为lamp用户
[lamp@localhost ~]$ cd /tmp
[lamp@localhost tmp]$ touch ftest

#建立测试文件
[lamp@localhost tmp]$ll ftest
-rw-rw-r-- 1 lamp lamp Apr 19 06:36 ftest
[lamp@localhost tmp]$ su - lamp1
#省略输入lamp1用户密码的过程,切换成lamp1用户
[lamp1 @localhost ~]$ cd /tmp/
[lamp1 @localhost tmp]$ rm -rf ftest

rm:cannot remove 'ftest':Operation not permitted

可以看到,虽然 /tmp 目录的权限设定是 777,但由于其具有 SBIT 权限,因此 lamp 用户在此目录创建的文件 ftest,lamp1 用户删除失败。

有兴趣的读者也可以尝试使用 lamp1 用户修改 lamp 用户创建的 ftest 文件中的内容,你会发现根本修改不了,这就是 SBIT 权限的作用。

 

 

9.15 Linux文件特殊权限(SUID、SGID和SBIT)的设置

 

前面已经学习 SUID、SGID、SBIT 特殊权限,以及各自的含义和功能,那么,如何给文件或目录手动设定这些特殊权限呢?

还是要依赖 chmod 命令。我们知道,使用 chmod 命令给文件或目录设定权限,有 2 种方式,分别是使用数字形式和字母形式。例如:

#数字形式
[root@localhost ~]# chmod 755 ftest
#字母形式
[root@localhost ~]# chmod u=rwx,go=rx ftest

给文件或目录设定 SUID、SGID 和 SBIT 特殊权限,也可以使用这 2 种形式。

有关 chmod 命令的用法,可以阅读《Linux chmod命令》一节。

我们知道,给 chmod 命令传递 3 个数字,即可实现给文件或目录设定普通权限。比如说,"755" 表示所有者拥有 rwx 权限,所属组拥有 rx 权限,其他人拥有 tx 权限。

给文件或目录设定特殊权限,只需在这 3 个数字之前增加一个数字位,用来放置给文件或目录设定的特殊权限,就这么简单。

因此,我们有必要知道 SUID、SGID、SBIT 分别对应的数字,如下所示:

4 --> SUID
2 --> SGID
1 --> SBIT

举个例子,如果要将一个文件权限设置为 -rwsr-xr-x,怎么办呢?此文件的普通权限为 755,另外,此文件还有 SUID 权限,因此只需在 755 的前面,加上 SUID 对应的数字 4 即可。也就是说,只需执行chmod 4755 文件名命令,就完成了-rwsr-xr-x 权限的设定。

关于 -rwsr-xr-x 的普通权限是 755,你可以这样理解,标记有 s 和 t 的权限位,隐藏有 x 权限,对此,本节后续会给出更详细的解释。

同样的道理,如果某文件拥有 SUID 和 SGID 权限,则只需要给 chmod 命令传递 6---(- 表示数字)即可;如果某目录拥有 SGID 和 SBIT,只需要给 chmod 命令传递 3--- 即可。

注意,不同的特殊权限,作用的对象是不同的,SUID 只对可执行文件有效;SGID 对可执行文件和目录都有效;SBIT 只对目录有效。当然,你也可以给文件设置 7---,也就是将 SUID、SGID、SBIT赋予一个文件或目录,例如:

[root@localhost ~]# chmod 7777 ftest
#一次赋予SetUID、SetGID和SBIT权限
[root@localhost ~]# ll ftest
-rwsrwsrwt. 1 root root Apr 19 23:54 ftest

执行过程虽然没有报错,但这样做,没有任何实际意义。

除了赋予 chmod 命令 4 个数字设定特殊权限,还可以使用字母的形式。例如,可以通过 "u+s" 给文件赋予 SUID 权限;通过 "g+s" 给文件或目录赋予 SGID 权限;通过 "o+t" 给目录赋予 SBIT 权限。

举一个例子:

[root@localhost ~]#chmod u+s, g+s, o+t ftest
#设置特殊权限
[root@localhost ~]# ll ftest
-rwsr-sr-t. 1 root root Apr 19 23:54 ftest
[root@localhost ~]# chmod u-s, g-s, o-t ftest
#取消特殊权限
[root@localhost ~]# ll ftest
-rwxr-xr-x. 1 root root Apr 19 23:54 ftest

例子中,通过字母的形式成功给 ftest 文件赋予了 3 种特殊权限,此做法仅为验证字母形式的可行性,对 ftest 文件来说,并无实际意义。

细心的读者可能发现这样一个问题,使用 chmod 命令给文件或目录赋予特殊权限时,原文件或目录中存在的 x 权限会被替换成 s 或 t,而当我们使用 chmod 命令消除文件或目录的特殊权限时,原本消失的 x 权限又会显现出来。

这是因为,无论是 SUID、SGID 还是 SBIT,它们只针对具有 x 权限的文件或目录有效。没有 x 权限的文件或目录,即便赋予特殊权限,也无法发挥它们的功能,没有任何意义。

例如,我们就是要给不具有 x 权限的文件或目录赋予特殊权限,看看有什么效果:

[root@localhost ~]# chmod 7666 ftest
[root@localhost ~]# ll ftest

-rwSrwSrwT. 1 root root Apr 23:54 ftest

可以看到,相应的权限位会被标记为 S(大写)和 T(大写),指的就是设置的 SUID、SGID 和 SBIT 权限没有意义。

 

9.16 Linux修改文件或目录的隐藏属性(chattr命令)

 

管理 Linux 系统中的文件和目录,除了可以设定普通权限和特殊权限外,还可以利用文件和目录具有的一些隐藏属性。

chattr 命令,专门用来修改文件或目录的隐藏属性,只有 root 用户可以使用。该命令的基本格式为:

[root@localhost ~]# chattr [+-=] [属性] 文件或目录名

+ 表示给文件或目录添加属性,- 表示移除文件或目录拥有的某些属性,= 表示给文件或目录设定一些属性。

表 1 列出了常用的一些属性及功能。

表 1 chattr 命令常用的属性选项及功能
属性选项 功能
i 如果对文件设置 i 属性,那么不允许对文件进行删除、改名,也不能添加和修改数据;
如果对目录设置 i 属性,那么只能修改目录下文件中的数据,但不允许建立和删除文件;
a 如果对文件设置 a 属性,那么只能在文件中増加数据,但是不能删除和修改数据;
如果对目录设置 a 属性,那么只允许在目录中建立和修改文件,但是不允许删除文件;
u 设置此属性的文件或目录,在删除时,其内容会被保存,以保证后期能够恢复,常用来防止意外删除文件或目录。
s 和 u 相反,删除文件或目录时,会被彻底删除(直接从硬盘上删除,然后用 0 填充所占用的区域),不可恢复。


【例 1】 给文件赋予 i 属性。

[root@localhost ~]# touch ftest
#建立测试文件
[root@localhost ~]# chattr +i ftest
[root@localhost ~]# rm -rf ftest

rm:cannot remove 'ftest':Operation not permitted
#无法删除"ftesr",操作不允许
#被赋予i属性后,root不能删除
[root@localhost ~]# echo 111>>ftest
bash:ftest:Permission denied
#权限不够,不能修改文件中的数据

可以看到,设置有 i 属性的文件,即便是 root 用户,也无法删除和修改数据。

【例 2】为目录赋予 i 属性。

[root@localhost ~]# mkdir dtest
#建立测试目录
[root@localhost dtest]# touch dtest/abc
#再建立一个测试文件abc
[root@localhost ~]# chattr +i dtest
#给目录赋予i属性
[root@localhost ~]# cd dtest
[root@localhost dtest]# touch bed

touch: cannot touch 'bed':Permission denied
#无法创建"bcd",权限不够,dtest目录不能新建文件
[root@localhost dtest]# echo 11>>abc
[root@localhost dtest]# cat abc

11
#可以修改文件内容
[root@localhost dtest]# rm -rf abc
rm: cannot remove 'abc': Permission denied
#无法删除"abc",权限不够

一旦给目录设置 i 属性,即使是 root 用户,也无法在目录内部新建或删除文件,但可以修改文件内容。

给设置有 i 属性的文件删除此属性也很简单,只需将 chattr 命令中 + 改为 - 即可。


【例 3】演示 a 属性的作用。
假设有这样一种应用,我们每天自动实现把服务器的日志备份到指定目录,备份目录可设置 a 属性,变为只可创建文件而不可删除。命令如下:

[root@localhost ~]# mkdir -p /back/log
#建立备份目录
[root@localhost ~]# chattr +a /back/log
#赋予a属性
[root@localhost ~]# cp /var/log/messages /back/log
#可以复制文件和新建文件到指定目录中
[root@localhost ~]# rm -rf /back/log/messages
rm: cannot remove '/back/log/messages': Permission denied
#无法删除 /back/log/messages,操作不允许


注意,通常情况下,不要使用 chattr 命令修改 /、/dev/、/tmp/、/var/ 等目录的隐藏属性,很容易导致系统无法启动。另外,chatrr 命令常与 lsattr 命令合用,前者修改文件或目录的隐藏属性,后者用于查看是否修改成功。有关 lsattr 命令,放到下节讲解。

 

 

 

9.17 Linux查看文件或目录的隐藏属性(lsattr命令)

 

使用 chattr 命令配置文件或目录的隐藏属性后,可以使用 lsattr 命令查看。

lsattr 命令,用于显示文件或目录的隐藏属性,其基本格式如下:

[root@localhost ~]# lsattr [选项] 文件或目录名


常用选项有以下 3 种:

  • -a:后面不带文件或目录名,表示显示所有文件和目录(包括隐藏文件和目录)
  • -d:如果目标是目录,只会列出目录本身的隐藏属性,而不会列出所含文件或子目录的隐藏属性信息;
  • -R:和 -d 恰好相反,作用于目录时,会连同子目录的隐藏信息数据也一并显示出来。


【例 1】

[root@localhost ~]# touch attrtest
-----------e- attrtest
[root@localhost ~]# chattr +aij attrtest
[root@localhost ~]# lsattr attrtest

----ia---j-e- attrtest

注意,不使用任何选项,仅用于显示文件的隐藏信息,不适用于目录。

【例 2】

[root@localhost ~]#lsattr -a
-----------e- ./.
------------- ./..
-----------e- ./.gconfd
-----------e- ./.bashrc
...


【例 3】

[root@localhost ~]#lsattr -d /back/log
-----a------e- /back/log
#查看/back/log目录,其拥有a和e属性

 

 

9.18 Linux sudo命令(包含和su命令的对比)

 

我们知道,使用 su 命令可以让普通用户切换到 root 身份去执行某些特权命令,但存在一些问题,比如说:

  • 仅仅为了一个特权操作就直接赋予普通用户控制系统的完整权限;
  • 当多人使用同一台主机时,如果大家都要使用 su 命令切换到 root 身份,那势必就需要 root 的密码,这就导致很多人都知道 root 的密码;


考虑到使用 su 命令可能对系统安装造成的隐患,最常见的解决方法是使用 sudo 命令,此命令也可以让你切换至其他用户的身份去执行命令。

相对于使用 su 命令还需要新切换用户的密码,sudo 命令的运行只需要知道自己的密码即可,甚至于,我们可以通过手动修改 sudo 的配置文件,使其无需任何密码即可运行。

sudo 命令默认只有 root 用户可以运行,该命令的基本格式为:

[root@localhost ~]# sudo [-b] [-u 新使用者账号] 要执行的命令

常用的选项与参数:

  • -b  :将后续的命令放到背景中让系统自行运行,不对当前的 shell 环境产生影响。
  • -u  :后面可以接欲切换的用户名,若无此项则代表切换身份为 root 。
  • -l:此选项的用法为 sudo -l,用于显示当前用户可以用 sudo 执行那些命令。


【例 1】

[root@localhost ~]#  grep sshd /etc/passwd
sshd:x:74:74:privilege-separated SSH:/var/empty/sshd:/sbin.nologin
[root@localhost ~]#  sudo -u sshd touch /tmp/mysshd
[root@localhost ~]#  ll /tmp/mysshd

-rw-r--r-- 1 sshd sshd 0 Feb 28 17:42 /tmp/mysshd

本例中,无法使用 su - sshd 的方式成功切换到 sshd 账户中,因为此用户的默认 Shell 是 /sbin/nologin。这时就显现出 sudo 的优势,我们可以使用 sudo 以 sshd 的身份在 /tmp 目录下创建 mysshd 文件,可以看到,新创建的 mysshd 文件的所有者确实是 sshd。

【例 2】

[root@localhost ~]#  sudo -u vbird1 sh -c "mkdir ~vbird1/www; cd ~vbird1/www; \
>  echo 'This is index.html file' > index.html"
[root@localhost ~]#  ll -a ~vbird1/www
drwxr-xr-x 2 vbird1 vbird1 4096 Feb 28 17:51 .
drwx------ 5 vbird1 vbird1 4096 Feb 28 17:51 ..
-rw-r--r-- 1 vbird1 vbird1   24 Feb 28 17:51 index.html

这个例子中,使用 sudo 命令切换至 vbird1 身份,并运行 sh -c 的方式来运行一连串的命令。

前面说过,默认情况下 sudo 命令只有 root 身份可以使用,那么,如何让普通用户也能使用它呢?

解决这个问题之前,先给大家分析一下 sudo 命令的执行过程。sudo命令的运行,需经历如下几步:

  • 当用户运行 sudo 命令时,系统会先通过 /etc/sudoers 文件,验证该用户是否有运行 sudo 的权限;
  • 确定用户具有使用 sudo 命令的权限后,还要让用户输入自己的密码进行确认。出于对系统安全性的考虑,如果用户在默认时间内(默认是 5 分钟)不使用 sudo 命令,此后使用时需要再次输入密码;
  • 密码输入成功后,才会执行 sudo 命令后接的命令。


显然,能否使用 sudo 命令,取决于对 /etc/sudoers 文件的配置(默认情况下,此文件中只配置有 root 用户)。所以接下来,我们学习对 /etc/sudoers 文件进行合理的修改。

sudo命令的配置文件/etc/sudoers

修改 /etc/sudoers,不建议直接使用 vim,而是使用 visudo。因为修改 /etc/sudoers 文件需遵循一定的语法规则,使用 visudo 的好处就在于,当修改完毕 /etc/sudoers 文件,离开修改页面时,系统会自行检验 /etc/sudoers 文件的语法。

因此,修改 /etc/sudoers 文件的命令如下:

[root@localhost ~]# visudo
…省略部分输出…
root ALL=(ALL) ALL  <--大约 76 行的位置
# %wheel ALL=(ALL) ALL   <--大约84行的位置
#这两行是系统为我们提供的模板,我们参照它写自己的就可以了
…省略部分输出…

通过 visudo 命令,我们就打开了 /etc/sudoers 文件,可以看到如上显示的 2 行信息,这是系统给我们提供的 2 个模板,分别用于添加用户和群组,使其能够使用 sudo 命令。

这两行模板的含义分为是:

root ALL=(ALL) ALL
#用户名 被管理主机的地址=(可使用的身份) 授权命令(绝对路径)
#%wheel ALL=(ALL) ALL
#%组名 被管理主机的地址=(可使用的身份) 授权命令(绝对路径)

表 1 对以上 2 个模板的各部分进行详细的说明。

表 1 /etc/sudoers 用户和群组模板的含义
模块 含义
用户名或群组名 表示系统中的那个用户或群组,可以使用 sudo 这个命令。
被管理主机的地址 用户可以管理指定 IP 地址的服务器。这里如果写 ALL,则代表用户可以管理任何主机;如果写固定 IP,则代表用户可以管理指定的服务器。如果我们在这里写本机的 IP 地址,不代表只允许本机的用户使用指定命令,而是代表指定的用户可以从任何 IP 地址来管理当前服务器。
可使用的身份 就是把来源用户切换成什么身份使用,(ALL)代表可以切换成任意身份。这个字段可以省略。
授权命令 表示 root 把什么命令命令授权给用户,换句话说,可以用切换的身份执行什么命令。需要注意的是,此命令必须使用绝对路径写。默认值是 ALL,表示可以执行任何命令。


【例 3】
授权用户 lamp 可以重启服务器,由 root 用户添加,可以在 /etc/sudoers 模板下添加如下语句:

[root@localhost ~]# visudo
lamp ALL=/sbin/shutdown -r now

注意,这里也可以写多个授权命令,之间用逗号分隔。用户 lamp 可以使用 sudo -l 查看授权的命令列表:

[root@localhost ~]# su - lamp
#切换成lamp用户
[lamp@localhost ~]$ sudo -l
[sudo] password for lamp:
#需要输入lamp用户的密码
User lamp may run the following commands on this host:
(root) /sbin/shutdown -r now

可以看到,lamp 用户拥有了 shutdown -r now 的权限。这时,lamp 用户就可以使用 sudo 执行如下命令重启服务器:

[lamp@localhost ~]$ sudo /sbin/shutdown -r now

再次强调,授权命令要使用绝对路径(或者把 /sbin 路径导入普通用户 PATH 路径中,不推荐使用此方式),否则无法执行。

【例 4】
假设现在有 pro1,pro2,pro3 这 3 个用户,还有一个 group 群组,我们可以通过在 /etc/sudoers 文件配置 wheel 群组信息,令这 3 个用户同时拥有管理系统的权限。

首先,向 /etc/sudoers 文件中添加群组配置信息:

[root@localhost ~]# visudo
....(前面省略)....
%group     ALL=(ALL)    ALL
#在 84 行#wheel这一行后面写入

此配置信息表示,group 这个群组中的所有用户都能够使用 sudo 切换任何身份,执行任何命令。接下来,我们使用 usermod 命令将 pro1 加入 group 群组,看看有什么效果:

[root@localhost ~]# usermod -a -G group pro1
[pro1@localhost ~]# sudo tail -n 1 /etc/shadow <==注意身份是 pro1
....(前面省略)....
Password:  <==输入 pro1 的口令喔!
pro3:$1$GfinyJgZ$9J8IdrBXXMwZIauANg7tW0:14302:0:99999:7:::
[pro2@localhost ~]# sudo tail -n 1 /etc/shadow <==注意身份是 pro2
Password:
pro2 is not in the sudoers file.  This incident will be reported.
#此错误信息表示 pro2 不在 /etc/sudoers 的配置中。

可以看到,由于 pro1 加入到了 group 群组,因此 pro1 就可以使用 sudo 命令,而 pro2 不行。同样的道理,如果我们想让 pro3 也可以使用 sudo 命令,不用再修改 /etc/sudoers 文件,只需要将 pro3 加入 group 群组即可。

 

 

9.19 结合实例分析Linux权限对指令执行的影响

 

通过本章的学习我们知道,权限对于使用者账号是非常重要的,因为它可以限制使用者是否能读取、建立、删除、修改文件或目录。

本节将结合前面章节学到的有关文件系统管理的指令,通过几个实例向大家说明,权限对 Linux 指令执行的重要性。

【实例 1】
让当前用户进入某指定目录,可以使用什么指令?需要具备何种权限?

用户可以使用 cd 指令,同时要想使此命令成功执行,需要用户对要进入的目录具有 x 权限。另外,如果用户还想要在此目录中使用 ls 命令,还需要对此目录具有 r 权限。


【实例 2】
如果想在某目录内读取一个文件,可以使用什么指令?需要具备何种权限?

用户可以使用 cat、more、less 等指令,并且该用户对此目录至少需要具有 x 权限,对读取的文件需要具有 r 权限。


【实例 3】
如果想修改一个文件,可以使用什么指令?需要具备何种权限?

可以使用 vim 编辑器,对于权限方面,用户至少需要对该文件所在目录具有 x 权限,同时对该文件具有 r、w 权限。


【实例 4】
要想让使用者 Linuxer 能够执行 cp /dir1/file1 /dir2 的指令,则 Linuxer 需要对 dir1、file1、dir2 分别具备哪些权限。

执行 cp 命令时,Linuxer 要能够读取指定文件,并且能够写入目标文件,因此:

  • dir1:至少需要有 x 权限;
  • file1:至少需要有 r 权限;
  • dir2:至少需要有 w,x 权限。


【实例 5】
有一个文件,其绝对路径为 /home/student/www/index.html,其中各个相关文件或者目录的权限分别如下所示:

drwxr-xr-x 23    root     root 4096 Sep 22 12:09 /
drwxr-xr-x  6    root     root 4096 Sep 22 02:09 /home
drwx------  6 student student 4096 Sep 22 02:10 /home/student
drwxr-xr-x  6 student student 4096 Sep 22 02:10 /home/student/www
drwxr--r--  6 student student  369 Sep 22 02:11 /home/student/www/index.html

那么,当使用 test 这个账号(不属于 student 群组)能够成功读取 index.html 这个文件呢?

因为目录结构是由根目录一层一层读取的,通过分析以上各个目录和文件的权限得知,对于 vbird 账号来说,它可以进入 /home,但却不可以进入 /home/student,因此可以判定,vbird 无法成功读取 index.html 文件中的内容。

 

 

 

你可能感兴趣的:(Ubuntu)