如何防止调用者的shell在sudo中被使用

Mik*_*e S 10 bash sudo environment-variables

我在 CentOS 6.5 上运行 sudo-1.8.6。我的问题很简单:如何防止 SHELL 从用户环境传播到 sudo 环境?

通常人们会走另一条路——他们想保留一个环境变量。但是,我遇到了一个问题,我的用户“zabbix”的 shell/sbin/nologin试图通过 sudo 运行命令。Sudo 保留了 ,/sbin/nologin以便 root 无法运行子shell。(更新:这部分是正确的,但它不是 SHELL 环境变量。问题是从 /etc/passwd 中提取的 shell 值。)

我包括一个说明问题的测试;这不是我的真实用例,但它只是说明调用用户的 SHELL 被保留。我有一个以 user 身份运行的程序zabbix。它调用/usr/bin/sudo -u root /tmp/doit(作为zabbix守护进程运行的编程,因此/sbin/nologin密码文件中的shell 不会阻止它)。/tmp/doit是一个 shell 脚本,它只有:

#!/bin/sh
env > /tmp/outfile
Run Code Online (Sandbox Code Playgroud)

(它的模式显然是 755)。在outfile我可以看到的SHELL/sbin/nologin。但是,此时脚本是通过 sudo 以 root 身份运行的,所以它应该没有以前用户的环境变量,对吧?

这是我的 /etc/sudoers:

默认要求
默认值 !visiblepw

默认值 always_set_home
默认值 env_reset
默认值 env_keep = "颜色显示主机名 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:/usr/local/bin:/usr/local/sbin

##允许root在任何地方运行任何命令 
根 ALL=(ALL) ALL

#includedir /etc/sudoers.d

这是我的/etc/sudoers.d/zabbix

默认值:zabbix !requiretty

zabbix ALL=(root) NOPASSWD: /tmp/doit

编辑:更多信息:

运行sudo的过程是zabbix_agentd,来自Zabbix监控软件。文件中有一个条目,/etc/zabbix/zabbix_agentd.d/userparameter_disk.conf如下所示:

UserParameter=example.disk.discovery,/usr/local/bin/zabbix_raid_discovery

/usr/local/bin/zabbix_raid_discovery是一个 Python 脚本。我已将其修改为简单地执行以下操作:

打印 subprocess.check_output(['/usr/bin/sudo', '-u', 'root', '/tmp/doit'])

/tmp/doit 只是这样做:

#!/bin/sh
环境 >> /tmp/outfile

我在我的 Zabbix 服务器上运行以下命令来运行/usr/local/bin/zabbix_raid_discovery脚本:

zabbix_get -s client_hostname -k 'example.disk.discovery'

然后我检查/tmp/outfile,我看到:

SHELL=/sbin/nologin
术语=linux
用户=root
SUDO_USER=zabbix
SUDO_UID=497
用户名=root
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
邮件=/var/mail/root
手残=/
LANG=en_US.UTF-8
SHLVL=1
SUDO_COMMAND=/tmp/doit
家=/root
日志名=根
SUDO_GID=497
_=/bin/env

那条SHELL线真的让我很烦恼。该文件归 root 所有,所以我知道它是由 root 用户创建的,但 shell 来自调用用户 ( zabbix)。

Mik*_*e S 5

然后答案是sudo有一个错误。首先,解决方法:我把它放在我的/etc/sudoers.d/zabbix file

zabbix ALL=(root) NOPASSWD: /bin/env SHELL=/bin/sh /usr/local/bin/zabbix_raid_discovery

现在从zabbix_raid_discovery工作中调用子命令。

修复此问题的补丁将在 sudo 1.8.15 中。来自维护者 Todd Miller:

这只是“一直都是这样”的一个例子。没有
真的是一个很好的理由。下面的差异应该使行为
匹配文档。

 - 托德

diff -r adb927ad5e86 插件/sudoers/env.c
--- a/plugins/sudoers/env.c 2015 年 10 月 6 日星期二 09:33:27 -0600
+++ b/plugins/sudoers/env.c 2015 年 10 月 6 日星期二 10:04:03 -0600
@@ -939,8 +939,6 @@
            CHECK_SETENV2("用户名", runas_pw->pw_name,
                ISSET(didvar,DID_USERNAME),真);
        } 别的 {
- 如果 (!ISSET(didvar, DID_SHELL))
- CHECK_SETENV2("SHELL", sudo_user.pw->pw_shell, false, true);
            /* 我们稍后会在 def_set_logname 的情况下设置 LOGNAME。*/
            如果(!def_set_logname){
                如果 (!ISSET(didvar, DID_LOGNAME))
@@ -984,6 +982,8 @@
            如果 (!env_should_delete(*ep)) {
                if (strncmp(*ep, "SUDO_PS1=", 9) == 0)
                    ps1 = * ep + 5;
+ else if (strncmp(*ep, "SHELL=", 6) == 0)
+ SET(didvar, DID_SHELL);
                否则 if (strncmp(*ep, "PATH=", 5) == 0)
                    设置(didvar,DID_PATH);
                否则 if (strncmp(*ep, "TERM=", 5) == 0)
@@ -1039,7 +1039,9 @@
     如果(reset_home)
        CHECK_SETENV2("HOME", runas_pw->pw_dir, true, true);

- /* 如果 $TERM 和 $PATH 未设置,则为它们提供默认值。*/
+ /* 如果未设置,则为 $SHELL、$TERM 和 $PATH 提供默认值。*/
+ if (!ISSET(didvar, DID_SHELL))
+ CHECK_SETENV2("SHELL", runas_pw->pw_shell, false, false);
     如果(!ISSET(didvar,DID_TERM))
        CHECK_PUTENV("TERM=unknown", false, false);
     如果(!ISSET(didvar,DID_PATH))