Как предотвратить использование оболочки вызывающей стороны в 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.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.