Запуск скриптов из программ Perl CGI с правами суперпользователя

У меня есть Perl CGI, который должен позволить пользователю выбирать некоторые файлы из файловой системы, а затем отправлять их через Rsync на удаленный сервер. Весь HTML создается сценарием Perl, и я использую строки запроса и временные файлы, чтобы создать иллюзию транзакции с отслеживанием состояния. Часть Rsync представляет собой отдельный сценарий оболочки, который вызывается с именем файла в качестве аргумента (скрипт также отправляет электронные письма и кучу других вещей, поэтому я просто не переместил его в сценарий Perl). Я хотел использовать sudo без пароля и настроил sudoers, чтобы пользователь apache мог запускать скрипт без пароля и отключил requiretty, но в журнале все равно появляются ошибки об отсутствии tty. Затем я попытался использовать su -c scriptname, но это тоже не помогло.

TD;DR Является ли ужасной практикой использование сценария Perl CGI для вызова сценария Bash через sudo, и как вы справляетесь с повышением привилегий для сценариев Perl CGI? Perl 5.10 на ядре Linux 2.6.

Соответствующий код: (LFILE — это файл, содержащий индексы для массива всех файлов в файловой системе)

elsif ( $ENV{QUERY_STRING} =~ 'yes' ) {
      my @CMDLINE = qw(/bin/su -c /bin/scriptname.sh);
      print $q->start_html;
      open('TFILE', '<', "/tmp/LFILE");
      print'<ul>';
      foreach(<TFILE>) {
         $FILES[$_] =~ s/\/.*\///g;
         print "Running command @CMDLINE $FILES[$_]";
         print $q->h1("Sending File: $FILES[$_]") ; `@CMDLINE $FILES[$_]` or print $q->h1("Problem: $?);

person GL2014    schedule 24.07.2014    source источник
comment
Ужасно ли использовать сценарий Perl CGI для вызова сценария Bash через sudo... Да, это так. Вместо этого настройте ключи SSH для пользователя без полномочий root.   -  person ThisSuitIsBlackNot    schedule 24.07.2014
comment
Ответ на мою проблему был -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no   -  person GL2014    schedule 26.07.2014
comment
Это не очень хорошее решение, так как оно оставляет вас открытыми для атак посредника, поскольку вы больше не проверяете, является ли хост, к которому вы подключаетесь, тем хостом, которым вы его считаете. Предоставление вашему веб-серверу привилегий суперпользователя через sudo также является очень плохой идеей (TM).   -  person ThisSuitIsBlackNot    schedule 26.07.2014
comment
Я не мог заставить scp/rsync и т. д. работать, когда CGI вызывает их через обратные кавычки или system() из-за отсутствия tty. Каково правильное решение этой проблемы?   -  person GL2014    schedule 26.07.2014
comment
Одним из вариантов является использование системы очередей. Все, что делает ваш CGI, — это добавляет задания в очередь; другая (не CGI) программа, работающая от имени привилегированного пользователя, извлекает задания из очереди и запускает их. Это решает многие вопросы безопасности. Обратите внимание, что большинство систем очередей работают по сети, поэтому программа, выполняющая задания, может работать в удаленной системе. См. этот аналогичный вопрос для дополнительных предложений.   -  person ThisSuitIsBlackNot    schedule 27.07.2014
comment
Да, на самом деле я пришел к этому решению для другой веб-интерфейсной программы, для которой требуется привилегированный контент. Это не ужасная идея. Спасибо.   -  person GL2014    schedule 28.07.2014
comment
Я бы использовал CGi, чтобы добавить запись в таблицу рабочей очереди в базе данных, а затем запустить задание cron, которое запускается от имени пользователя root и запускает rsync. Отделяйте просьбу от исполнения. Таким образом, у вас будет более тонкий контроль над обработкой.   -  person Len Jaffe    schedule 30.07.2014


Ответы (1)


Однако вы в конечном итоге делаете это, вы должны быть осторожны. Вы хотите минимизировать вероятность атаки повышения привилегий. Имея это в виду….

sudo — не единственный способ, которым пользователь (или процесс) может выполнять код с повышенными привилегиями. Для такого рода приложений я бы использовал программу с установленным битом setuid.

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

  2. Установите «бит setuid» в программе, выполнив что-то вроде:

    chmod a+x,u+s transfer_file
    

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

  3. Вызовите (привилегированную) программу передачи из существующего (непривилегированного) сценария CGI.

Теперь, чтобы сохранить требуемые привилегии как можно ниже, я бы настоятельно избегал выполнения переноса от имени root. Вместо этого создайте отдельного пользователя, у которого есть необходимые привилегии для передачи файлов, но не более, и сделайте этого пользователя владельцем программы setuid. Таким образом, даже если программа открыта для эксплуатации, эксплуататор может использовать привилегии этого пользователя, а не root.

Есть несколько важных «подводных камней» при настройке чего-то подобного. Если у вас возникли проблемы, спросите еще раз на этом сайте.

person Tim    schedule 21.09.2014