Какой самый безопасный способ для программной записи в файл с правами root?

Огромному приложению необходимо в один конкретный момент выполнить небольшое количество записей в файл, требующий прав root. Это не файл, а аппаратный интерфейс, который подпадает под Linux как файл.

Чтобы избежать предоставления прав root для всего приложения, я написал сценарий bash, который выполняет критические задачи. Например, следующий сценарий будет включать порт 17 аппаратного интерфейса в качестве вывода:

echo "17" > /sys/class/gpio/export echo "out" > /sys/class/gpio/gpio17/direction 

Однако, поскольку suid отключен для скриптов bash в моей системе, мне интересно, какой лучший способ это сделать.

  1. Используйте некоторое обходное решение, представленное здесь.

  2. Вызовите скрипт с sudo из основного приложения и соответствующим образом отредактируйте список sudoers, чтобы избежать необходимости использования пароля при вызове скрипта. Мне немного неудобно давать привилегии sudo для echo .

  3. Просто напишите программу C с fprintf и установите для нее suid root. Жестко обозначьте строки и имена файлов и убедитесь, что только root может его отредактировать. Или прочитайте строки из текстового файла, аналогично убедившись, что никто не может редактировать файл.

  4. Некоторое другое решение, которое мне не приходило, более безопасно или проще, чем те, которые были представлены выше?

6 Solutions collect form web for “Какой самый безопасный способ для программной записи в файл с правами root?”

Вам не нужно предоставлять sudo доступ к echo . На самом деле это бессмысленно, потому что, например, с помощью sudo echo foo > bar , перенаправление выполняется как исходный пользователь, а не как root.

Вызовите маленький скрипт с помощью sudo , позволяя NOPASSWD: доступ к ТОЛЬКО этому скрипту (и любым другим подобным скриптам) пользователям, которым нужен доступ к нему.

Это всегда лучший / безопасный способ использования sudo . Изолируйте небольшое количество команд, которым необходимы привилегии root, в их собственный отдельный сценарий (ы) и разрешите недоверному или частично доверенному пользователю запускать этот скрипт только с правами root.

Маленький скрипт sudo -able должен либо не брать аргументы (или входные данные) от пользователя (т.е. любые другие программы, которые он вызывает, должны иметь жестко запрограммированные параметры и аргументы), либо он должен очень тщательно проверять любые аргументы / ввод, которые он имеет принимать от пользователя.

Будьте параноидальными в проверке – вместо того, чтобы искать «известные плохие» вещи, чтобы исключить, разрешить только «известные хорошие» вещи и прервать любые несоответствия или ошибки или что-либо даже подозрительное.

Проверка должна выполняться как можно раньше (желательно, прежде чем он сделает чтолибо еще с правами root).


Я действительно должен был упомянуть об этом, когда я впервые написал этот ответ, но если ваш скрипт является скриптом оболочки, он ДОЛЖЕН правильно процитировать все переменные. Будьте особенно осторожны, чтобы процитировать переменные, содержащие входные данные, предоставленные пользователем каким-либо образом, но не предполагайте, что некоторые переменные безопасны, QUOTE THEM ALL .

Это включает переменные среды, потенциально контролируемые пользователем (например, "$PATH" , "$HOME" , "$USER" и т. Д. И определенно включая "$QUERY_STRING" и "HTTP_USER_AGENT" т. Д. В сценарии CGI). Фактически, просто цитируйте их все. Если вам нужно построить командную строку с несколькими аргументами, используйте массив для построения списка args и "${myarray[@]}" что – "${myarray[@]}" .

Я уже говорил «процитировать их все»? Запомни. сделай это.

Проверьте владельца на файлах gpio:

 ls -l /sys/class/gpio/ 

Скорее всего, вы узнаете, что они принадлежат группе gpio :

 -rwxrwx--- 1 root gpio 4096 Mar 8 10:50 export ... 

В этом случае вы можете просто добавить своего пользователя в группу gpio для предоставления доступа без sudo:

 sudo usermod -aG gpio myusername 

После этого вам нужно будет выйти из системы и снова войти в систему, чтобы изменения вступили в силу.

Одним из решений для этого (особенно используемого на рабочем столе Linux, но также применимым в других случаях) является использование D-Bus для активации небольшой службы, выполняемой как root и polkit для авторизации. Это принципиально, для чего был разработан полкит; из его вводной документации :

polkit предоставляет API авторизации, предназначенный для использования привилегированными программами («МЕХАНИЗМЫ»), предлагающими услуги непривилегированным программам («КЛИЕНТЫ»). См. Страницу руководства polkit для архитектуры системы и большой картины.

Вместо того, чтобы выполнять вашу вспомогательную программу, большая, непривилегированная программа отправляет запрос на шину. Ваш помощник может быть запущен как демон, запущенный при загрузке системы, или, лучше, активироваться по мере необходимости системой . Затем этот помощник будет использовать polkit для проверки того, что запрос поступает из авторизованного места. (Или, в этом случае, если это кажется излишним, вы можете использовать какой-то другой жесткий код аутентификации / авторизации механизма.)

Я нашел хорошую базовую статью о передаче через D-Bus , и пока я ее не тестировал, это, по-видимому, является основным примером добавления polkit в микс .

В этом подходе ничто не должно быть отмечено setuid.

Один из способов сделать это – сделать программу setuid-root, написанную на C, которая делает только то, что нужно, и не более того. В вашем случае он вообще не должен смотреть на любой пользовательский ввод.

 #include <unistd.h> #include <string.h> #include <stdio.h> // for perror(3) // #include ... more stuff for open(2) static void write_str_to_file(const char*fn, const char*str) { int fd = open(fn, O_WRONLY) if (-1 == fd) { perror("opening device file"); // make this a CPP macro instead of function so you can use string concat to get the filename into the error msg exit(1); } int err = write(fd, str, strlen(str)); // ... error check err = close(fd); // ... error check } int main(int argc, char**argv) { write_string_to_file("/sys/class/gpio/export", "17"); write_string_to_file("/sys/class/gpio/gpio17/direction", "out"); return 0; } 

Невозможно подорвать это через переменные среды или что-то еще, потому что все, что он делает, это сделать несколько системных вызовов.

Недостаток: вы должны проверить возвращаемое значение каждого системного вызова.

Потенциал: проверка ошибок очень проста: если есть какая-либо ошибка, просто perror и запустите: выход с ненулевым статусом. Если есть ошибка, исследуйте с помощью strace . Вам не нужна эта программа, чтобы давать действительно приятные сообщения об ошибках.

Bless tee вместо echo для sudo – это один из распространенных способов приближения к ситуации, когда вам нужно ограничить корневой поток. Переадресация на / dev / null заключается в том, чтобы остановить утечку любого выхода – тройник делает то, что вы хотите.

 echo "17" | sudo tee /sys/class/gpio/export > /dev/null echo "out" | sudo tee /sys/class/gpio/gpio17/direction > /dev/null 

Вы можете создать скрипт, который выполняет желаемую задачу. Затем создайте новую учетную запись пользователя, которая может только войти в систему, предоставив ключ, используемый OpenSSH.

Примечание. Любой пользователь сможет запустить этот скрипт, если у него есть файл ключа, поэтому убедитесь, что файл ключа OpenSSH не доступен для чтения кем-либо, которого вы хотите предотвратить от выполнения задачи.

В конфигурации OpenSSH (в файле authorized_keys) перед указанием ключа укажите команду (за которой следует пробел), как описано в этом «примерном» тексте:

command="myscript" keydata optionalComment

Этот параметр конфигурации может ограничивать использование ключа OpenSSH только при выполнении определенной команды. Теперь у вас есть sudo, предоставляющий разрешения, но конфигурация OpenSSH – это часть решения, которое действительно используется для ограничения / ограничения того, что этот пользователь может сделать, чтобы пользователь не выполнял другие команды. Это также не так сложно с конфигурационным файлом «sudo», поэтому, если вы используете OpenBSD или если новые «doas» («делать») OpenBSD начинают становиться более популярными (с будущими версиями любой операционной системы, которую вы используете) , вам не нужно будет подвергать сомнению сложность конфигурации sudo.

  • Программы setuid, похоже, не запускают setuid в TinyCore Linux
  • Почему Ubuntu не использует возможности для ping?
  • Что означает GID?
  • ptrace suid binaries после отмены привилегии
  • Что означает атрибут 's' в разрешениях файлов?
  • Почему setuid не работает?
  • Разрешения каталога «rs», chmod 655 не изменяется на «rx», почему?
  • Apache suexec не будет работать с strace
  • Почему ping требует разрешения setuid?
  • Принцип наименьшей привилегии: действительно ли помощнику Authbind нужен root setuid или он может работать с cap_net_bind_services?
  • Отладить двоичный файл setuid как не root
  • Interesting Posts
    Linux и Unix - лучшая ОС в мире.