Как предотвратить использование оболочки вызывающей стороны в sudo

8

Я использую sudo-1.8.6 на CentOS 6.5. У меня очень простой вопрос: как предотвратить распространение SHELL из среды пользователя в среду sudo?

Обычно люди идут другим путем - они хотят сохранить переменную среды. Однако у меня возникла проблема, когда мой пользователь "zabbix", чья оболочка /sbin/nologinпытается выполнить команду через sudo. Sudo сохраняет /sbin/nologinтак, что root не может запускать подоболочки. (Обновление: эта часть верна, но это не переменная среды SHELL. Проблема заключается в том, что значение оболочки извлекается из / etc / passwd.)

Я включаю тест, который иллюстрирует проблему; это не мой реальный пример использования, но он просто показывает, что ОБОЛОЧКА вызывающего пользователя сохраняется. У меня есть программа, которая работает как пользователь zabbix. Он вызывает /usr/bin/sudo -u root /tmp/doit(программа работает как zabbixдемон, поэтому /sbin/nologinоболочка в файле паролей не мешает этому). /tmp/doitскрипт оболочки, который просто имеет:

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

(его режим 755, очевидно). В outfileя могу видеть , что SHELLесть /sbin/nologin. Однако в этот момент скрипт запускается с правами root через sudo, поэтому в нем не должно быть переменных окружения предыдущего пользователя, верно?

Вот мой / etc / sudoers:

Значения по умолчанию requiretty
Значения по умолчанию! 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 запускать любые команды где угодно 
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 / местные / бен / zabbix_raid_discovery

/usr/local/bin/zabbix_raid_discoveryскрипт Python Я изменил это, чтобы просто сделать это:

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

/tmp/doit просто делает это:

#! / Bin / ш
env >> / tmp / outfile

Я запускаю следующее на своем Zabbix сервере, чтобы запустить /usr/local/bin/zabbix_raid_discoveryскрипт:

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

Затем я проверяю /tmp/outfileи вижу:

SHELL = / SBIN / NOLOGIN
TERM = Linux
USER = корень
SUDO_USER = Zabbix
SUDO_UID = 497
USERNAME = корень
PATH = / SBIN: / бен: / USR / SBIN: / USR / бен: / USR / местные / бен: / USR / местные / SBIN
MAIL = / вар / почта / корень
PWD = /
ЛАНГ = en_US.UTF-8
SHLVL = 1
SUDO_COMMAND = / TMP / DoIt
НАЧАЛО = / корень
LOGNAME = корень
SUDO_GID = 497
_ = / Bin / окр

Эта SHELLлиния действительно беспокоит меня. Файл принадлежит пользователю root, поэтому я знаю, что он создается пользователем root, но оболочка от вызывающего пользователя ( zabbix).

Майк С
источник
sudo env SHELL=/bin/sh shПредоставляет ли в вашей системе приглашение / bin / sh, установленное в качестве переменной SHELL?
@adonis - см. мой обновленный вопрос. Кстати, ты очень красивый.
Майк С
@BinaryZebra - Да , я знаю о env_delete, но я согласен суть проблемы заключается в том, что поведение по умолчанию env_reset У ...causes commands to be executed with a new, minimal environment.нас есть система Linux с PAM, поэтому по странице человека, The new environment contains the ... SHELL ... (variable). Как вы можете видеть из моего /etc/sudoersфайла выше, мы не разрешаем SHELLв env_keep. Так SHELLне должно быть сохранено; у нас должен быть пользователь root SHELL.
Майк С
@BinaryZebra - я добавил zabbix ALL=(root) NOPASSWD: /bin/env SHELL=/bin/sh /tmp/doit *в свой /etc/sudoers/zabbixфайл, и он имеет надлежащую оболочку. Спасибо, теперь у меня есть обходной путь. Вопрос в том, зачем мне это включать? Передача SHELL вызывающей стороны кажется опасной (и неработающей), но я не могу найти места, где sudo настроен для ее изменения. Я бежал find /etc/sudoers /etc/sysconfig -type f -exec grep env_ {} \;и не нахожу красных флажков; /etc/sudoersсодержит единственную env_строку. Так что я не думаю, что есть флаг sudoers, вмешивающийся ...
Майк S
Майк: На первом уровне: простой sudo bashдолжен запустить оболочку bash от имени пользователя root, и для него ДОЛЖНА быть установлена ​​переменная SHELL в значение из / etc / password. Вы сообщаете, что SHELL устанавливается (или сохраняется как) /sbin/nologin. Это проблема безопасности, оболочка, запускаемая root, не должна контролироваться переменной окружения, установленной пользователем. Это то, что вы должны исследовать.

Ответы:

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. От сопровождающего Тодда Миллера:

Это просто случай "это всегда было так". Нет
действительно хорошая причина для этого. Разница ниже должна сделать поведение
соответствовать документации.

 - Тодд

плагины diff -r adb927ad5e86 / sudoers / env.c
--- a / plugins / sudoers / env.c вт 06 окт. 09:33:27 2015 -0600
+++ b / плагины / sudoers / env.c вт 06 октября 10:04:03 2015 -0600
@@ -939,8 +939,6 @@
            CHECK_SETENV2 ("ИМЯ ПОЛЬЗОВАТЕЛЯ", runas_pw-> pw_name,
                ISSET (didvar, DID_USERNAME), правда);
        } еще {
- если (! ISSET (дидвар, DID_SHELL))
- CHECK_SETENV2 ("SHELL", sudo_user.pw-> pw_shell, false, true);
            / * Мы установим LOGNAME позже в случае def_set_logname. * /
            if (! def_set_logname) {
                если (! 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 (дидвар, DID_SHELL);
                иначе if (strncmp (* ep, "PATH =", 5) == 0)
                    SET (дидвар, DID_PATH);
                иначе if (strncmp (* ep, "TERM =", 5) == 0)
@@ -1039,7 +1039,9 @@
     if (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);
     if (! ISSET (didvar, DID_TERM))
        CHECK_PUTENV ("TERM = unknown", false, false);
     если (! ISSET (didvar, DID_PATH))
Майк С
источник
Отличный Майк! Спасибо за детективную работу.
Майк, возможно, ты поставил ссылку на (будущий?) Патч.
@BinaryZebra Diff здесь: sudo.ws/repos/sudo/rev/b77adbc08c91 Я пока не вижу патча.
Майк С
Майк: я верю, что ты лаешь не на то дерево. Ключевой момент здесь: Provide default values for $SHELL, $TERM and $PATH if not set.это: ... if not set.. Любое установленное значение будет сохранено с помощью sudo. Кто настраивает SHELL?
@BinaryZebra - Я не так его читаю. SHELL не установлен (по умолчанию env_reset). Поскольку он не установлен, старый код говорит использовать запись pw sudo_user. Новый код говорит использовать запись pw пользователя runas.
Майк С
4

Вопрос был в том, где, по моему мнению, была проблема, но оказалось, что проблема не в том, что происходит с переменной SHELL, а в том, что на самом деле делает sudo. Например:

-bash-4.1 $ whoami
testdude
-bash-4.1 $ grep testdude / etc / passwd
testdude: x: 1001: 10: тестовый чувак: / tmp: / bin / bash
-bash-4.1 $ sudo env
[sudo] пароль для testdude: 
...
SHELL = / bin / Баш
...

Все идет нормально. ... но проблема в том, что sudo использует оболочку вызывающей стороны вместо вызываемой, в отличие от документации. Действительно, если я изменю свою оболочку, отредактировав / etc / passwd, вы увидите, что sudo следует за оболочкой вызывающей стороны, а не SHELL:

-bash-4.1 $ grep root / etc / passwd
корень: х: 0: 0: корень: / корень: / Bin / Баш
-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 env
...
SHELL = / бен / ш
...
-bash-4.1 $ export SHELL = / полностью / бессмысленно / путь
-bash-4.1 $ sudo env
...
SHELL = / бен / ш
...

Я не могу использовать, sudo -iпотому что я не хочу имитировать начальный логин. sudo -sбудет работать, пока у меня есть правильная команда в файле sudoers. Тем не менее, ожидаемое поведение (как отражено в справочной странице: " The new environment contains the TERM, PATH, HOME, MAIL, SHELL, LOGNAME, USER, USERNAME and SUDO_* variables") для оболочки должно быть вызываемым. Если вы посмотрите на PATH, HOME, LOGNAMEи USERпеременные для Судо ENV вы увидите вещи суперпользователя. SHELLтакже должна быть оболочкой root.

Майк С
источник