每天学五分钟 Liunx 011 | sudo
回顾前两节,在 001 中介绍了怎么添加用户及用户组,在 010 中介绍了从 client 端 ssh 到 server 的详细过程,那么接下来要介绍的就是是登陆到 server 之后如何切换用户了。
留一道真题: server 中有三个用户 lianhua,huasheng 和 lianhuasheng。lianhua 想把自己提权成 root,它自己没有权限去改 root 的文件,不过 huasheng 可以执行一些属于 root 的命令,试问这时候要怎么做才能让 lianhua 提权到 root?
su
提权到 root 有两种方式,第一种就是 su 了,查看 su 的解释:
[root@controller-0 sudoers.d]# su --help
Usage:
su [options] [-] [USER [arg]...]
Change the effective user id and group id to that of USER.
A mere - implies -l. If USER not given, assume root.
Options:
-m, -p, --preserve-environment do not reset environment variables
-g, --group <group> specify the primary group
-G, --supp-group <group> specify a supplemental group
-, -l, --login make the shell a login shell
-c, --command <command> pass a single command to the shell with -c
--session-command <command> pass a single command to the shell with -c
and do not create a new session
-f, --fast pass -f to the shell (for csh or tcsh)
-s, --shell <shell> run shell if /etc/shells allows it
-h, --help display this help and exit
-V, --version output version information and exit
通过 su 加指定 user 的方式将当前用户提权到指定用户(一般是 root)。su 提示输的密码是要提权用户的密码:
[lianhua@***n ~]$ su - root
Password:
Last login: Sat Mar 7 17:55:48 CST 2020 on pts/0
[root@*** ~]# env
XDG_SESSION_ID=5763
HOSTNAME=***
SHELL=/bin/bash
TERM=xterm
HISTSIZE=1000
http_proxy=http://10.110.***.***
USER=root
LS_COLORS=36:*.xspf=01;36:
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/root
LANG=en_US.UTF-8
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
LOGNAME=root
LESSOPEN=||/usr/bin/lesspipe.sh %s
_=/bin/env
之所以登陆之后要 show 环境变量 env 的原因是因为加了 - 的提权方式是 login shell 的,也就是提权到指定用户之后环境变量都会变成指定用户的环境变量,如果不用 - 的话,会出现这样的情况:
[lianhua@*** ~]$ su root
Password:
[root@*** ~]# env
XDG_SESSION_ID=5763
HOSTNAME=***
TERM=xterm
SHELL=/bin/bash
HISTSIZE=1000
USER=lianhua
http_proxy=http://10.110.***.***
LS_COLORS=36:*.xspf=01;36:
PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/lianhua/.local/bin:/home/lianhua/bin
MAIL=/var/spool/mail/lianhua
PWD=/home/lianhua
LANG=en_US.UTF-8
HISTCONTROL=ignoredups
HOME=/root
SHLVL=2
LOGNAME=lianhua
LESSOPEN=||/usr/bin/lesspipe.sh %s
_=/bin/env
可以看到虽然提前到 root 了,但是环境变量还是 huasheng 的,这也意味着要使用一些 root 用户才能用的命令需要使用绝对路径来指定该命令,相当麻烦!
虽然 su 可以提权到 root , 但是通过 su 提权需要知道 root 的密码,如果用户多的话,很容易泄露 root 账号的密码,这是很危险的。针对这种情况,一个更安全的提权方式 sudo 就派上用场了。
sudo
sudo 可以让非 root 用户在不需要知道 root 用户密码的情况下,提权到 root 执行 root 用户才能执行的命令。
查看 sudo 选项:
Options:
-A, --askpass use a helper program for password prompting
-b, --background run command in the background
-C, --close-from=num close all file descriptors >= num
-E, --preserve-env preserve user environment when running command
--preserve-env=list preserve specific environment variables
-e, --edit edit files instead of running a command
-g, --group=group run command as the specified group name or ID
-H, --set-home set HOME variable to target user's home dir
-h, --help display help message and exit
-h, --host=host run command on host (if supported by plugin)
-i, --login run login shell as the target user; a command may also be specified
-K, --remove-timestamp remove timestamp file completely
-k, --reset-timestamp invalidate timestamp file
-l, --list list user's privileges or check a specific command; use twice for longer format
-n, --non-interactive non-interactive mode, no prompts are used
-P, --preserve-groups preserve group vector instead of setting to target's
-p, --prompt=prompt use the specified password prompt
-r, --role=role create SELinux security context with specified role
-S, --stdin read password from standard input
-s, --shell run shell as the target user; a command may also be specified
-t, --type=type create SELinux security context with specified type
-T, --command-timeout=timeout terminate command after the specified time limit
-U, --other-user=user in list mode, display privileges for user
-u, --user=user run command (or edit file) as specified user name or ID
-V, --version display version information and exit
-v, --validate update user's timestamp without running a command
-- stop processing command line arguments
可以通过 sudo -u <user> <command> 的方式来指定要提权的 user 所执行的 command,如果不指定 user 的话默认提权到 root。
对 lianhua 进行提权执行 passwd 命令:
[lianhua@*** ~]$ sudo passwd
[sudo] password for lianhua:
Sorry, user lianhua is not allowed to execute '/bin/passwd' as root on controller-0-forestgreen.
与 su 提权输入密码不一样的是:这里 sudo 需要输入的密码是 lianhua 密码,这点要注意。
那么问题来了,为什么 lianhua 不能执行 passwd 命令呢?
原因在于文件 /etc/sudoers 需要修改相应的配置才能让 lianhua 执行 passwd。
通过 visudo 工具查看 /etc/sudoers ,这个工具会检查 /etc/sudoers 有没有修改,修改的格式对不对。
[root@test ~]visudo
...
root ALL=(ALL) ALL
...
主要参数是 root ALL=(ALL) ALL 这一项,列出来单独讨论。
每项表示的意义是:
用户账号 登陆者的来源主机名=[可切换的身份] 可执行的命令
root ALL = (ALL) ALL
用户账号: 要使用 sudo 命令的账号;
登陆者的来源主机名: 表示允许登陆的主机,如果不为 ALL 则表示授权用户只能在指定主机上登陆 server 执行 sudo 命令。
可切换的身份: 当前用户可以这个身份来执行后面的命令,默认提权到 root。
可执行的命令: 切换的身份可以执行的命令,这个命令是绝对路径,不能用相对路径!试想如果一个用户造了一个命令也叫 passwd,如果执行命令用相对路径,用户执行 passwd 的话执行到这个造出来的 passwd 命令,那是相当危险的!
查看 huasheng 这个用户在 /etc/sudoers 里的配置:
[root@*** ~]visudo
...
huasheng ALL=(ALL) NOPASSWD:/usr/sbin/visudo
...
与前面有一点点不一样的是,huasheng 多了一个 NOPASSWD 字段,这是因为使用 sudo 提权执行命令的时候会提示输入当前用户的密码,很麻烦,所以管理员也就是我给它加了个 NOPASSWD 字段,这样就不用每次输密码了。
好了,那我们好好玩一玩 huasheng,首先把登陆者的来源主机名改掉,改成 hostname 对应的 ip,然后把这个 ip 加到 huasheng 的登陆者来源主机名中:
[root@*** ~]# hostname
test
[root@*** ~]# hostname -I
10.57.0.1
[root@*** ~]# visudo
...
huasheng 10.57.0.1=(ALL) NOPASSWD:/usr/sbin/visudo
...
[root@*** ~]# su - huasheng
Last login: Sat Mar 7 16:06:10 CST 2020 on pts/0
[huasheng@*** ~]$ sudo visudo
visudo: /etc/sudoers.tmp unchanged
<关于 hostname 详解可看这里>
把这个 ip 改成其它主机的 ip 看看能不能执行 visudo:
[huasheng@*** ~]# visudo
...
huasheng 10.57.1.1=(ALL) NOPASSWD:/usr/sbin/visudo
...
[huasheng@*** ~]$ sudo visudo
[sudo] password for huasheng:
huasheng is not allowed to run sudo on test. This incident will be reported.
提示 hausheng 不能在当前主机 test 上执行这个 visudo 命令!
把 ip 改回来,把 huasheng 的可切换身份改为 lianhua 执行 visudo 看看:
[root@test ~]# visudo
[root@test ~]# su - huasheng
Last login: Sat Mar 7 19:27:29 CST 2020 on pts/0
[huasheng@test ~]$ sudo visudo
[sudo] password for huasheng:
Sorry, user huasheng is not allowed to execute '/sbin/visudo' as root on test.
提示的很明显,huasheng 没有提权到 root,所以不能执行 visudo 命令!
真题演练
折腾半天 huasheng 了,也得看看 lianhua 咋滴了,他还是没法提权切不了 root 。再回看开头的问题,结合前面的分析应该知道怎么提权了,直接给答案:
[lianhua@test ~]$ su - huasheng
Password:
Last login: Sat Mar 7 19:52:44 CST 2020 on pts/0
[huasheng@test ~]$ which su
/bin/su
[huasheng@controller-0-forestgreen ~]$ sudo visudo
...
lianhua ALL=(ALL) NOPASSWD: /bin/su
...
[huasheng@test ~]$ exit
logout
[lianhua@test ~]$ sudo su
[root@test lianhua]#
题目还有个用户 lianhuasheng ,看看他的配置:
[root@test lianhua]# visudo
...
lianhuasheng ALL=(ALL) NOPASSWD: /bin/su
...
他的配置和 hausheng / lianhua 一样,那么把他们三个加到一个组,起名叫 ADMINGROUP ,这个组里的用户可以提权到 root。但是要给他们设置不能执行 passwd 和 passwd root 命令,不然他们就能把原来的 root 密码给改掉了,这样是很危险的!
在 /etc/sudoers 中,组的配置是在组名前加 % 号表示,同时禁用某个命令是在命令前加 ! 号,* 号作为通配符表示可以执行目录下一系列命令。
[root@test lianhua]# groupadd ADMINGROUP
[root@test lianhua]# visudo
...
%ADMINGROUP ALL=(ALL) NOPASSWD: /bin/su, !/bin/passwd, !/bin/passwd root
...
[root@test lianhua]# usermod -G ADMINGROUP lianhua
[root@test lianhua]# usermod -G ADMINGROUP huasheng
[root@test lianhua]# usermod -G ADMINGROUP lianhuasheng
[root@test lianhua]# su - lianhua
Last login: Sat Mar 7 19:56:00 CST 2020 on pts/0
[lianhua@test ~]$ sudo su
[root@test lianhua]#
现在我们改提权的方式都是直接改的 /etc/sudoers 文件,但是系统推荐的更好的方式是在 /etc/sudoers.d/ 目录下新建配置的用户。/etc/sudoers 文件默认已经配置了该目录:
[root@test ~]# cat /etc/sudoers | grep sudoers.d
## Read drop-in files from /etc/sudoers.d (the # here does not mean a comment)
#includedir /etc/sudoers.d
再把 ADMINGROUP 移到 /etc/sudoers.d 目录下,重新配置这三个用户:
[root@test lianhua]# cd /etc/sudoers.d/
[root@test sudoers.d]# vi ADMINGROUP
%ADMINGROUP ALL=(ALL) NOPASSWD: /bin/su
[root@test sudoers.d]# visudo
[root@test sudoers.d]# su - lianhua
Last login: Sat Mar 7 20:17:35 CST 2020 on pts/0
[lianhua@test ~]$ sudo su
[root@test lianhua]#
(完)
芝兰生于空谷,不以无人而不芳。