Cómo evitar que la concha de la persona que llama se use en sudo

8

Estoy ejecutando sudo-1.8.6 en CentOS 6.5. Mi pregunta es muy simple: ¿cómo evito que SHELL se propague del entorno de un usuario a un entorno de sudo?

Por lo general, las personas van por el otro lado: quieren preservar una variable de entorno. Sin embargo, tengo un problema en el que mi usuario "zabbix" cuyo shell /sbin/nologinintenta ejecutar un comando a través de sudo. Sudo está preservando /sbin/nologinpara que la raíz no pueda ejecutar subcapas. (Actualización: esta parte es verdadera, pero no es la variable de entorno SHELL. El problema es el valor de shell que se extrae de / etc / passwd).

Incluyo una prueba que ilustra el problema; Este no es mi caso de uso del mundo real, sino que simplemente ilustra que el SHELL del usuario que llama se conserva. Tengo un programa que se ejecuta como usuario zabbix. Llama /usr/bin/sudo -u root /tmp/doit(la programación se ejecuta como zabbixun demonio, por lo que el /sbin/nologinshell en el archivo de contraseña no lo impide). /tmp/doites un script de shell que simplemente tiene:

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

(su modo es 755, obviamente). En outfilepuedo ver que SHELLes /sbin/nologin. Sin embargo, en este punto, el script se ejecuta como root, a través de sudo, por lo que no debería tener las variables de entorno del usuario anterior, ¿verdad?

Aquí está mi / etc / sudoers:

Los valores predeterminados requieren
Por defecto! Visiblepw

Valores predeterminados always_set_home
Valores predeterminados env_reset
Valores predeterminados env_keep = "PANTALLA DE COLORES NOMBRE DEL HOSTAL TAMAÑO INPUTRC KDEDIR LS_COLORS"
Valores predeterminados env_keep + = "CORREO PS1 PS2 QTDIR NOMBRE DE USUARIO LANG LC_ADDRESS LC_CTYPE"
Valores predeterminados env_keep + = "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Valores predeterminados env_keep + = "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Valores predeterminados env_keep + = "LC_TIME LC_ALL IDIOMA LINGUAS _XKB_CHARSET XAUTHORITY"
Valores predeterminados secure_path = / sbin: / bin: / usr / sbin: / usr / bin: / usr / local / bin: / usr / local / sbin

## Permitir a la raíz ejecutar cualquier comando en cualquier lugar 
root ALL = (ALL) ALL

#includedir /etc/sudoers.d

Y aquí está mi /etc/sudoers.d/zabbix:

Valores predeterminados: zabbix! Requiretty

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

Editar: Un poco más de información:

El proceso que ejecuta el sudo es zabbix_agentd, desde el software de monitoreo Zabbix. Hay una entrada en el /etc/zabbix/zabbix_agentd.d/userparameter_disk.confarchivo que se parece a:

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

/usr/local/bin/zabbix_raid_discoveryes un script de Python Lo he modificado para simplemente hacer esto:

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

/tmp/doit simplemente hace esto:

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

Ejecuto lo siguiente en mi servidor Zabbix para ejecutar el /usr/local/bin/zabbix_raid_discoveryscript:

zabbix_get -s client_hostname -k 'ejemplo.disco.discovery'

Luego reviso el /tmp/outfile, y veo:

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

Esa SHELLlínea realmente me molesta. El archivo es propiedad de root, por lo que sé que está siendo creado por el usuario root, pero el shell es del usuario llamante ( zabbix).

Mike S
fuente
¿ sudo env SHELL=/bin/sh shProporciona un aviso con / bin / sh establecido como la variable SHELL en su sistema?
@adonis: vea mi pregunta actualizada. Por cierto, eres muy guapo.
Mike S
@BinaryZebra - Sí sé acerca env_delete, pero estoy de acuerdo el quid de la cuestión es que el comportamiento predeterminado de env_reset ...causes commands to be executed with a new, minimal environment.Tenemos un sistema Linux con PAM, lo que de acuerdo a la página del manual, The new environment contains the ... SHELL ... (variable). Como puede ver en mi /etc/sudoersarchivo anterior, no permitimos SHELLen el env_keep. Por SHELLlo tanto , no se debe preservar; deberíamos tener el usuario root SHELL.
Mike S
@BinaryZebra: he agregado zabbix ALL=(root) NOPASSWD: /bin/env SHELL=/bin/sh /tmp/doit *a mi /etc/sudoers/zabbixarchivo y tiene un shell adecuado. Gracias, ahora tengo una solución. La pregunta es, ¿por qué necesitaba incluirlo? Parece peligroso (y roto) pasar el SHELL de la persona que llama, pero no puedo encontrar ningún lugar donde sudo esté configurado para modificarlo. He corrido find /etc/sudoers /etc/sysconfig -type f -exec grep env_ {} \;y no encuentro banderas rojas; /etc/sudoerscontiene la única env_cadena Así que no creo que haya una bandera sudoers interfiriendo ...
Mike S
Mike: en un primer nivel: un simple sudo bash debe iniciar un shell bash como root y DEBE tener la variable SHELL establecida en el valor de / etc / password. Usted informa que SHELL se está configurando en (o se conserva como) /sbin/nologin. Ese es un problema de seguridad, el shell iniciado por root no debe ser controlado por una variable de entorno establecida por un usuario. Eso es algo que debes investigar.

Respuestas:

5

Entonces la respuesta es que sudotiene un error. Primero, la solución: puse esto en mi /etc/sudoers.d/zabbix file:

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

y ahora subcomandos llamados desde el zabbix_raid_discoverytrabajo.

Un parche para arreglar esto estará en sudo 1.8.15. Del mantenedor, Todd Miller:

Este es solo un caso de "siempre ha sido así". No hay
Realmente una buena razón para ello. El diff a continuación debe hacer el comportamiento
coincide con la documentación.

 - todd

diff -r adb927ad5e86 plugins / sudoers / env.c
--- a / plugins / sudoers / env.c Mar 06 de octubre 09:33:27 2015 -0600
+++ b / plugins / sudoers / env.c Mar Oct 06 10:04:03 2015 -0600
@@ -939,8 +939,6 @@
            CHECK_SETENV2 ("USERNAME", runas_pw-> pw_name,
                ISSET (didvar, DID_USERNAME), verdadero);
        } más {
- if (! ISSET (didvar, DID_SHELL))
- CHECK_SETENV2 ("SHELL", sudo_user.pw-> pw_shell, falso, verdadero);
            / * Configuraremos LOGNAME más adelante en el caso def_set_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);
                más if (strncmp (* ep, "PATH =", 5) == 0)
                    SET (didvar, DID_PATH);
                más if (strncmp (* ep, "TERM =", 5) == 0)
@@ -1039,7 +1039,9 @@
     if (reset_home)
        CHECK_SETENV2 ("INICIO", runas_pw-> pw_dir, verdadero, verdadero);

- / * Proporcione valores predeterminados para $ TERM y $ PATH si no están configurados. * /
+ / * Proporcione valores predeterminados para $ SHELL, $ TERM y $ PATH si no está configurado. * /
+ if (! ISSET (didvar, DID_SHELL))
+ CHECK_SETENV2 ("SHELL", runas_pw-> pw_shell, falso, falso);
     if (! ISSET (didvar, DID_TERM))
        CHECK_PUTENV ("TERM = desconocido", falso, falso);
     if (! ISSET (didvar, DID_PATH))
Mike S
fuente
Excelente Mike !, gracias por el trabajo de detective.
Mike, ¿es posible que pongas un enlace al parche (¿futuro?).
@BinaryZebra Diff está aquí: sudo.ws/repos/sudo/rev/b77adbc08c91 Todavía no veo un parche.
Mike S
Mike: Creo que estás ladrando al árbol equivocado. El punto clave aquí: Provide default values for $SHELL, $TERM and $PATH if not set.es: ... if not set.. Cualquier valor establecido será preservado por sudo. ¿Quién está configurando SHELL?
@BinaryZebra: no es así como lo leí. SHELL no está configurado (por env_reset, por defecto). Como no está configurado, el código anterior dice que use la entrada pw de sudo_user. El nuevo código dice que use la entrada pw del usuario runas.
Mike S
4

La pregunta era sobre dónde pensé que estaba el problema, pero resulta que el problema no es qué le sucede a la variable SHELL, sino qué hace realmente sudo. Por ejemplo:

-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] contraseña para testdude: 
...
SHELL = / bin / bash
...

Hasta aquí todo bien. ... pero el problema es que sudo usa el shell de la persona que llama en lugar de la persona que llama, a diferencia de los documentos. De hecho, si cambio mi shell editando / etc / passwd, puede ver que sudo sigue el shell de la persona que llama y no 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 = / completamente / sin sentido / ruta
-bash-4.1 $ sudo env
...
SHELL = / bin / sh
...

No puedo usar sudo -iporque no quiero simular un inicio de sesión inicial. sudo -sfuncionará, siempre que tenga el comando adecuado en el archivo sudoers. Sin embargo, el comportamiento esperado (como se refleja en la página del manual: " The new environment contains the TERM, PATH, HOME, MAIL, SHELL, LOGNAME, USER, USERNAME and SUDO_* variables") es que el intérprete de comandos sea el llamado. Si nos fijamos en el PATH, HOME, LOGNAME, y USERvariables para sudo env verá las cosas de raíz. SHELLdebería ser también la cáscara de la raíz.

Mike S
fuente