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

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

我在 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运行的编程,因此密码文件中的 shell 不会阻止它)。是一个 shell 脚本,它只包含:zabbix/sbin/nologin/tmp/doit

#!/bin/sh
env > /tmp/outfile

(显然它的模式是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 用户名 LANG LC_ADDRESS LC_CTYPE"
默认值 env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASURMENT 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 在任何地方运行任何命令
根全部=(全部)全部

#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脚本。我已将其修改为简单地执行此操作:

print 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
苏多_UID=497
用户名=root
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
邮件=/var/mail/root
密码=/
LANG=en_US.UTF-8
SLVL=1
SUDO_COMMAND=/tmp/doit
首页=/根目录
日志名称=根
SUDO_GID=497
_=/bin/env

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

答案1

那么答案是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 日星期二 -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), true);
        } 别的 {
- if (!ISSET(didvar, DID_SHELL))
- CHECK_SETENV2("SHELL", sudo_user.pw->pw_shell, false, true);
            /* 我们稍后将在 def_set_logname 情况下设置 LOGNAME。 */
            if (!def_set_logname) {
                if (!ISSET(didvar, DID_LOGNAME))
@@ -984,6 +982,8 @@
            if (!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)
                    SET(didvar, DID_PATH);
                否则 if (strncmp(*ep, "TERM=", 5) == 0)
@@ -1039,7 +1039,9 @@
     如果(重置主页)
        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);
     if (!ISSET(didvar, DID_TERM))
        CHECK_PUTENV("TERM=未知", false, false);
     if (!ISSET(didvar, DID_PATH))

答案2

问题是我认为问题出在哪里,但事实证明问题不在于 SHELL 变量发生了什么,而是 sudo 实际做了什么。例如:

-bash-4.1$ whoami
测试哥们
-bash-4.1$ grep testdude /etc/passwd
testdude:x:1001:10:测试哥们:/tmp:/bin/bash
-bash-4.1$ sudo 环境
[sudo] testdude 的密码:
...
外壳=/bin/bash
...

到目前为止,一切都很好。 ...但问题是 sudo 使用调用者的 shell 而不是被调用者,这与文档相反。事实上,如果我通过编辑 /etc/passwd 来更改 shell,您可以看到 sudo 遵循调用者的 shell,而不是SHELL

-bash-4.1$ grep root /etc/passwd
根:x:0:0:根:/根:/bin/bash
-bash-4.1$ sudo sed -i -e '/testdude/s/bash/sh/' /etc/passwd
-bash-4.1$ grep testdude /etc/passwd
testdude:x:1001:10:测试哥们:/tmp:/bin/sh
-bash-4.1$ sudo 环境
...
外壳=/bin/sh
...
-bash-4.1$ 导出SHELL=/完全/无意义/路径
-bash-4.1$ sudo 环境
...
外壳=/bin/sh
...

我无法使用,sudo -i因为我不想模拟初始登录。sudo -s只要 sudoers 文件中有正确的命令,就可以工作。然而,预期的行为(如手册页中所反映的:“ The new environment contains the TERM, PATH, HOME, MAIL, SHELL, LOGNAME, USER, USERNAME and SUDO_* variables”)是 shell 是被调用者的。如果您查看sudo env 的PATHHOMELOGNAMEUSER变量,您将看到 root 的内容。SHELL也应该是 root 的 shell。

相关内容