September 11

Командная строка Linux, повышение привилегий: команды su, sudo

Командная строка Linux, повышение привилегий: команды su, sudo

Приветствую!

Продолжаем изучать командную строку Linux. Сегодня узнаем, как правильно запускать команды от имени другого пользователя, в том числе пользователя root. Познакомимся с командами su и sudo, а также изучим, как правильно предоставлять ограниченные полномочия для пользователей и групп.

Заодно разберем, почему sudo su – это как сказать: “Откройте мне дверь“, а потом еще раз потребовать: “И впустите меня немедленно!“😁.

Присоединяйтесь к нашему каналу в телеграм: t.me/r4ven_me, уведомления о новых постах приходят туда в день публикации. А если у вас есть вопросы или просто желание пообщаться по тематике – заглядывайте в чат: t.me/r4ven_me_chat.

Если вы новичок в мире Linux, то рекомендую изучить мои предыдущие статьи по командной строке:

Предисловие

Тема привилегий в Linux очень обширна. В данной статье мы только разберем работу с командами su и sudo, как наиболее популярными инструментами. Но существует также множество других механизмов, например capabilities, SELinux, AppArmor и в целом PolicyKit, ну и конечно ACL (Access Control Lists). Голову сломать можно, только от разнообразия🤯.

И так, приступим.

Команда su

su (Substitute User или Set UID или Switch User или Super User — замена/переключение пользователя, суперпользователь) — это классическая команда и одноименная утилита в Unix-подобных операционных системах, позволяющая пользователю войти в систему под другим именем, не завершив текущий сеанс. Чаще всего используется для выполнения некоторых команд или временного входа с правами суперпользователя с целью выполнения административных задач. Просто и понятно 😉.

Автором данной программы является Dennis Ritchie. Если верить англоязычной википедии, то первый релиз данной утилиты был 3 ноября, 1971 года. Почти 53 года назад😲. И несмотря на это, она до сих пор пользуется популярностью. Вот уж прям, философия Unix в действии: “программа должна выполнять одну задачу и делать это хорошо“.

И так синтаксис:

su [ключи] [-] [имя_пользователя]

Если не передать команде имя пользователя явно, будет использовано имя root.

Особенностью команды является запрос пароля при каждом ее выполнении. Только если она уже не выполняется от имени root пользователя.

Часто используемые ключи:

  • - или -l (login) – имитировать “полноценный” вход под оболочкой пользователя (make the shell a login shell);
  • -c (command) – выполнить переданную далее команду (в кавычках);
  • -g (group) – выполнить подмену группы пользователя, работает только для root.

Приступим к практике. Если ввести в терминал:

su -

У нас запросят пароль суперпользователя root, после чего мы переключимся на него.

Если команде явно передать имя желаемого пользователя, например:

su - ivan

То, соответственно, мы активируем сеанс оболочки от его имени.

Существует принципиальная разница, между указанием ключа - или -l и его отсутствием. Если ключ не указать, то при переходе на другого пользователя, ваш текущий рабочий каталог и часть окружения пользователя (env) не изменятся. Вот пример:

whoami

echo $USER

su

whoami

echo $USER
Команда whoami выводит в терминал имя текущего пользователя.

Тут видно, что после перехода под учетную запись суперпользователя, переменная окружения $USER, содержащая имя текущего пользователя, не обновилась. Про этот нюанс необходимо помнить, особенно при написании скриптов, если в них используется команда su.

Теперь попробуем выполнить единичную команду, без смены пользователя:

su -c 'whoami'

А теперь с использованием дефиса:

su -c 'pwd'

su - -c 'pwd'
Команда pwd (print working directory) выводит в терминал текущий рабочий каталог пользователя.

Надеюсь, разницу вы поняли. Ну и еще парочку примеров для закрепления.

С дефисом:

su -

su - ivan -c 'whoami'

Без:

su -c 'whoami && pwd'
Оператор контроля выполнения команд – && позволяет выполнить вторую команду, только при успешном выполнении предыдущей. Подробнее про такие операторы тут.

Команда sudo

sudo (англ. Substitute User and do, дословно «подменить пользователя и выполнить») — также является командой и одноименной утилитой, позволяющей делегировать определенные привилегированные ресурсы пользователям с ведением журнала их действий.

И я почти все время думал, что sudo = super user do 😳

sudo поставляется с большинством UNIX и UNIX-подобных операционных систем, но, к примеру, “чистый” Debian в этот список не входит. В случае данного дистрибутива, утилиту sudo необходимо устанавливать отдельно!

В отличие от классической su, sudo предоставляет более гибкие инструменты для настройки повышения привилегий. Чаще всего, с помощью sudo, задают четкий перечень команд, доступных для выполнения от имени другого пользователя, в т.ч. root.

Синтаксис:

sudo [ключи] команда

Часто используемые ключи:

  • -s (shell) – запустить оболочку от имени другого пользователя, тоже, что и sudo bash (как пример);
  • -i – также запустить оболочку от имени другого пользователя, но аналогично нативному входу в систему (login shell);
  • -u (user) – позволяет указать пользователя, от имени которого будет выполнена команда;
  • -e (edit) – выполнить редактирование файла, с использованием заданного в переменной $EDITOR консольного редактора (nano, vim);
  • -l (list) – вывести список доступных к запуску, с помощью sudo, команд;
  • -S (stdin) – принимать пароль из стандартного потока ввода (stdin);
  • -E (env) – запускать команды с сохранением окружения (env) текущего пользователя.

Ну а практику мы начнем, пожалуй, с одной распространенной, но весьма комичной ситуации – когда для получения root полномочий используют команду:

sudo su

По сути, в ней нет ничего страшного, но она неверна в синтаксическом плане.

Вместо нее рекомендуется использовать следующие команды:

sudo -s

# или

sudo -i

# или

su -

Дело в том, что при выполнении sudo su вы создаете лишний процесс. Получается одновременный запуск двух разных команд.

Для демонстрации, выполним:

sudo su

ps

exit

sudo -s

ps

Как видно в верхней части скрина, на один процесс больше🤷‍♂️.

Теперь попробуем выполнить отдельную команду, без перехода на другого пользователя:

sudo -u postgres 'whoami'
В данном примере используется пользователь postgres, от имени которого, по умолчанию, запускаются процессы СУБД PostgreSQL.

А чтобы перейти в оболочку другого пользователя (аналог su - <пользователь>) выполним:

sudo -iu postgres

whoami

pwd

В таком случае и рабочая директория и окружение будут целевого пользователя.

Файлы sudoers

Плавно подходим в основной фишке утилиты sudo – файлы sudoers. Это такие файлы, в которых следуя правилам строгого синтаксиса, можно тонко настроить разграничение полномочий для пользователей и групп.

Основной файл конфигурации расположен по пути: /etc/sudoers. Обычно он уже заполнен дефолтными и прокомментированными значениями.

По умолчанию, в данном файле уже заданы максимальные привилегии для группы sudo в Deb системах (Debian, Ubuntu, Linux Mint) и wheel для RPM (RHEL, Centos, Fedora, OpenSuse).

Почему wheel? Вероятно так исторически сложилось. Гугл перевод из англ. википедии: В операционных системах Unix термин «колесо» относится к учетной записи пользователя с битом колеса — системной настройкой, которая предоставляет дополнительные специальные системные привилегии, которые позволяют пользователю выполнять ограниченные команды, к которым обычные учетные записи пользователей не имеют доступа.

Пользователи такой группы имеют возможность выполнять переход в учетную запись root.

Для проверки выполните:

sudo cat /etc/sudoers

groups

Чтобы расширить стандартную конфигурацию sudo, рекомендуется создавать отдельные файлы в директории /etc/sudoers.d. Часто в разных дистрибутивах, там уже есть какие-то файлы. Например в Linux Mint лежит:

ls -l /etc/sudoers.d

Создавать такие файлы рекомендуется с помощью специальной команды visudo, которая перед сохранением файла проверяет его синтаксис, и в случае ошибки выводит предупреждение.

Давайте создадим такой файл. Но сперва выберем консольный редактор по умолчанию такой командой (для Deb систем):

sudo update-alternatives --config editor

Разумеется мы выбираем vi/vim/nvim😉, потому что я давненько не перезагружал компьютер😁

Перед внесением любых изменений в файлы sudoers, необходимо открыть несколько резервных терминалов с root сессией. Если допустить хотя бы одну ошибку в синтаксисе файла, root доступ через sudo пропадёт. Придется входить под root напрямую или использовать su. Я вас предупредил.

Теперь создадим файл с перечнем доступных команд для УЗ из примера выше – postgres и группы – ivan:

sudo visudo -f /etc/sudoers.d/postgres
Ключ -f используется для явного указания пути до sudoers файла.

Пример наполнения может быть такой:

Cmnd_Alias PG = \ 
    /usr/sbin/ldconfig, \ 
    /usr/sbin/setcap CAP_NET_ADMIN\,CAP_NET_BIND_SERVICE+epi /usr/lib/postgresql/16/bin/postgres, \ 
    /usr/bin/systemctl status postgresql, \
    /usr/bin/systemctl start postgresql, \
    /usr/bin/systemctl stop postgresql, \
    /usr/bin/systemctl restart postgresql, \
    /usr/bin/journalctl * postgresql, \
    /usr/bin/cat /var/log/auth.log

postgres ALL = (root) NOPASSWD: PG
%ivan ALL = (postgres) NOPASSWD: ALL

Сами команды я расписывать не буду, опишу лишь директивы sudoers:

  • Cmnd_Alias определяет псевдоним списка команд – PG (произвольный), который, собственно и содержит команды, разделенные запятой. Символ обратного слэша – это символ экранирования. Используется, например, для экранирования символов перевода строки или символа запятой, которая к слову, в sudoers является частью синтаксиса!
  • postgres ALL = (root) NOPASSWD: PG в этой строке:
    • postgres – учетная запись, для которой задается список команд, доступных через sudo;
    • ALL = – хосты, для которых разрешено использовать sudo;
    • (root) – пользователь, от имени которого разрешено выполнение указанных команд;
    • NOPASSWD: – отключение запроса пароля при выполнении команды через sudo;
    • PG – алиас, заданный параметром Cmnd_Alias
  • %ivan ALL = (postgres) NOPASSWD: ALL в этой строке:
    • %ivan – системная группа (в данном примере ivan), пользователи которой могут выполнять команды с помощью sudo от имени указанного далее пользователя;
    • ALL = – хосты, для которых разрешено использовать sudo;
    • (postgres) – пользователь, от имени которого разрешено выполнение указанных команд;
    • NOPASSWD: – отключение запроса пароля при выполнении команды через sudo;
    • ALL – возможность выполнять любые команды доступные указанному пользователю и от его имени.

Сохраняем и выходим из редактирования.

Если допустить ошибку, вы увидите такое сообщение с указанием места, где ошиблись:

Введите e и нажмите Enter для возврата в редактор. Про букву e нужно знать, т.к. никаких подсказок программа не дает, сурово однако🤔.

Если все заполнили корректно, то visudo позволит сохранить файл и закрыть редактор.

В примере выше, мы настроили полный доступ к пользователю postgres для членов группы ivan. А ему (postgres) в свою очередь, разрешили выполнять строгий перечень команд от имени root.

Проверяем:

sudo -l

sudo -iu postgres

sudo -l

При вводе разрешенной команды, она просто выполнится🤷‍♂️. А при использовании команды не из разрешенного списка, sudo у вас запросит пароль суперпользователя, и если его у вас нет, соответственно запретит ее выполнение. Пример:

sudo systemctl status postgresql

sudo systemctl enable postgresql

Ну вот, вроде все рассказал.

Ах да, совсем недавно я узнал, что при использовании sudo, переменная окружения $PATH становится неактуальной. Для утилиты sudo задается специальная директива secure_path в файле /etc/sudoers со списком директорий, где хранятся исполняемые файлы:

Defaults  secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/opt/bin"

Теперь и вы знаете об этом☺️.

Послесловие

Мы с вами сделали еще один шаг на пути изучения командной строки Linux. Как я уже сказал в начале статьи, тема привилегий, да и безопасности в целом, в мире Linux – очень обширна и будет всегда актуальной. Поэтому старайтесь уделять время не только изучению каких-то технологий, но и их безопасному использованию.

Если остались вопросы, приглашаю в вороний чат🐧. И, конечно, в наш канал Telegram: @r4ven_me, чтобы не пропустить новые посты😉.

Спасибо, что читаете. Успехов вам! И старайтесь все делать со здравой толикой безопасности.

Полезные материалы