Como evitar que o shell do chamador seja usado no sudo

8

Estou executando o sudo-1.8.6 no CentOS 6.5. Minha pergunta é muito simples: como evitar que o SHELL se propague do ambiente de um usuário para um ambiente sudo?

Geralmente as pessoas estão indo para o outro lado - elas querem preservar uma variável de ambiente. No entanto, estou tendo um problema onde o meu usuário "zabbix" cujo shell é /sbin/nologin tenta executar um comando via sudo. Sudo está preservando o /sbin/nologin para que o root não possa executar subshells. (Update: Esta parte é verdadeira, mas não é a variável de ambiente SHELL. É o valor do shell que está sendo extraído do / etc / passwd que é o problema.)

Eu incluo um teste que ilustra o problema; este não é o meu caso de uso do mundo real, mas simplesmente ilustra que o SHELL do usuário chamador é preservado. Eu tenho um programa que é executado como usuário zabbix . Ele chama /usr/bin/sudo -u root /tmp/doit (a programação sendo executada como zabbix é um daemon, portanto, o shell /sbin/nologin no arquivo de senha não o impede). /tmp/doit é um script de shell que simplesmente possui:

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

(seu modo é 755, obviamente). Em outfile , posso ver que SHELL é /sbin/nologin . No entanto, neste momento o script está rodando como root, via sudo, então não deveria ter as variáveis de ambiente do usuário anterior, certo?

Aqui está meu / etc / sudoers:

Defaults    requiretty
Defaults   !visiblepw

Defaults    always_set_home
Defaults    env_reset
Defaults    env_keep =  "COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR LS_COLORS"
Defaults    env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
Defaults    env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Defaults    env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Defaults    env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"
Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin

## Allow root to run any commands anywhere 
root    ALL=(ALL)       ALL

#includedir /etc/sudoers.d

E aqui está meu /etc/sudoers.d/zabbix :

Defaults:zabbix !requiretty

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

Editar: um pouco mais de informação:

O processo que executa o sudo é zabbix_agentd , do software de monitoramento Zabbix. Há uma entrada no arquivo /etc/zabbix/zabbix_agentd.d/userparameter_disk.conf que se parece com:

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

/usr/local/bin/zabbix_raid_discovery é um script Python. Eu modifiquei para simplesmente fazer isso:

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

/tmp/doit simplesmente faz isso:

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

Eu corro o seguinte no meu servidor Zabbix para executar o script /usr/local/bin/zabbix_raid_discovery :

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

Em seguida, verifico o /tmp/outfile e vejo:

SHELL=/sbin/nologin
TERM=linux
USER=root
SUDO_USER=zabbix
SUDO_UID=497
USERNAME=root
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
MAIL=/var/mail/root
PWD=/
LANG=en_US.UTF-8
SHLVL=1
SUDO_COMMAND=/tmp/doit
HOME=/root
LOGNAME=root
SUDO_GID=497
_=/bin/env

Essa linha SHELL realmente me incomoda. O arquivo é de propriedade de root, então eu sei que está sendo criado pelo usuário root, mas o shell é do usuário chamador ( zabbix ).

    
por Mike S 06.10.2015 / 00:02

2 respostas

5

A resposta é que sudo tem um erro. Primeiro, a solução alternativa: eu coloquei isso no meu /etc/sudoers.d/zabbix file :

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

e agora subcomandos chamados de zabbix_raid_discovery work.

Um patch para corrigir isso será no sudo 1.8.15. Do mantenedor, Todd Miller:

This is just a case of "it's always been like that".  There's not
really a good reason for it.  The diff below should make the behavior
match the documentation.

 - todd

diff -r adb927ad5e86 plugins/sudoers/env.c
--- a/plugins/sudoers/env.c     Tue Oct 06 09:33:27 2015 -0600
+++ b/plugins/sudoers/env.c     Tue Oct 06 10:04:03 2015 -0600
@@ -939,8 +939,6 @@
            CHECK_SETENV2("USERNAME", runas_pw->pw_name,
                ISSET(didvar, DID_USERNAME), true);
        } else {
-           if (!ISSET(didvar, DID_SHELL))
-               CHECK_SETENV2("SHELL", sudo_user.pw->pw_shell, false, true);
            /* We will set LOGNAME later in the def_set_logname case. */
            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);
                else if (strncmp(*ep, "PATH=", 5) == 0)
                    SET(didvar, DID_PATH);
                else if (strncmp(*ep, "TERM=", 5) == 0)
@@ -1039,7 +1039,9 @@
     if (reset_home)
        CHECK_SETENV2("HOME", runas_pw->pw_dir, true, true);

-    /* Provide default values for $TERM and $PATH if they are not set. */
+    /* Provide default values for $SHELL, $TERM and $PATH if not set. */
+    if (!ISSET(didvar, DID_SHELL))
+       CHECK_SETENV2("SHELL", runas_pw->pw_shell, false, false);
     if (!ISSET(didvar, DID_TERM))
        CHECK_PUTENV("TERM=unknown", false, false);
     if (!ISSET(didvar, DID_PATH))
    
por 06.10.2015 / 20:46
4

A questão era sobre onde eu pensava que o problema era, mas acontece que o problema não é o que acontece com a variável SHELL, mas o que o sudo realmente faz. Por exemplo:

-bash-4.1$ whoami
testdude
-bash-4.1$ grep testdude /etc/passwd
testdude:x:1001:10:Test dude:/tmp:/bin/bash
-bash-4.1$ sudo env
[sudo] password for testdude: 
...
SHELL=/bin/bash
...

Até aí tudo bem. ... mas o problema é que o sudo usa o shell do chamador em vez do chamado, ao contrário dos documentos. De fato, se eu mudar meu shell editando o / etc / passwd, você pode ver que o sudo segue o shell do chamador e não o SHELL :

-bash-4.1$ grep root /etc/passwd
root:x:0:0:root:/root:/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:Test dude:/tmp:/bin/sh
-bash-4.1$ sudo env
...
SHELL=/bin/sh
...
-bash-4.1$ export SHELL=/completely/meaningless/path
-bash-4.1$ sudo env
...
SHELL=/bin/sh
...

Eu não posso usar sudo -i porque não quero simular um login inicial. sudo -s funcionará, desde que eu tenha o comando apropriado no arquivo sudoers. No entanto, o comportamento esperado (conforme refletido na página man: " The new environment contains the TERM, PATH, HOME, MAIL, SHELL, LOGNAME, USER, USERNAME and SUDO_* variables ") é para o shell ser o chamado. Se você olhar as variáveis PATH , HOME , LOGNAME e USER para sudo env, você verá as coisas do root. SHELL também deve ser o shell do root.

    
por 06.10.2015 / 21:17