Разрешение PHP выполнять скрипт bash с правами root - PullRequest
5 голосов
/ 12 ноября 2010

как разрешить PHP-скрипту выполнять bash-скрипт с правами root?

Допустим, есть сценарий PHP ...

<?php
// location: /var/www/script.php
exec("bash /var/scripts/test.sh"); // "sudo bash ..." does not work
?>

и скрипт bash ...

#!/bin/bash
# location: /var/scripts/test.sh
sudo mkdir /test

Конечно, PHP и Apache не должны запускаться как root, и в лучшем случае только скрипт может быть выполнен с правами root. Есть идеи?

С уважением, Джимбо

Ответы [ 6 ]

6 голосов
/ 13 мая 2011

Если вы не хотите ждать cron, вот простая обёртка в C, которую вы будете вызывать с php.

#include <unistd.h>
#include <errno.h>
#define WEBUID 500
main( int argc, char ** argv, char ** envp ) {
    if( getuid() != WEBUID ) exit(1);
    /* some more security checks */
    if( setuid(geteuid()) ) perror( "setuid error" );
    envp = 0; /* don't want environment - security problem */
    system( "/hardcoded/path/to/script.bash", argv, envp );
}

Эта скомпилированная оболочка должна принадлежать пользователю root, группе "www" и иметь "s-bit".
chwon root.www wrapper; chmod 4440 wrapper, поэтому

  • при выполнении его эффективный UID будет root
  • выполнить его может только группа www (группа веб-сервера)
  • и когда UID вызывающего абонента не является веб-сервером, будет завершен
6 голосов
/ 12 ноября 2010

Любое решение на основе PHP, которое дает права root в некоторой точке цепочки, опасно: злоумышленник, имеющий доступ к пользователю PHP, может получить доступ к пользователю root, что недопустимо с точки зрения безопасности.

Я никогда не реализовывал это сам, но я предложу то, что я предложил здесь : при наличии задания сценария / cron с правами root часто сканируется какое-либо место на предмет наличия в сценарии PHP признака заданиядолжно быть сделано - например, файл с определенным именем или запись в базе данных заданий.

Если этот файл найден, корневой скрипт делает свое дело и снова удаляет файл.

Если ваш PHP-скрипт не нуждается в прямом ответе от корневого скрипта, я думаюэто был бы лучший путь.(Конечно, ответ может быть облегчен и корневым сценарием, записывающим сообщение о состоянии в файл).

Пока вы строго ограничиваете, какие виды работ PHP может писать для корневого сценария, этоявляется водонепроницаемым решением, так как оно не вовлекает пользователя root в бизнес PHP.

2 голосов
/ 07 декабря 2012

Вам нужно взглянуть на incron (cron для событий файловой системы). Попросите php записать в файл и установите incron для запуска вашего скрипта после закрытия записанного в файл файла (incron очень специфичен). Ваш сценарий, вероятно, должен также санировать входной файл, чтобы предотвратить внедрение кода, и использовать команду lockfile, а также, чтобы предотвратить любые расы между несколькими пользователями сети.

У меня есть мини-веб-интерфейс, где можно включить анонимный FTP или другие сервисы на 1 час с паролем. www работает с обычными привилегиями, как и www-data (пользователь php), но incron вызывает скрипт обработки ввода как root.

Mike

1 голос
/ 13 мая 2011

Вам может не понадобиться PHP или Apache для запуска с правами root. Если у вас есть контроль над вашим сервером, вы можете использовать модуль Apache с именем suPHP и указать пользователя, которого вы хотите запустить Apache, как для ваших php-скриптов в конфигурации. Вы можете сделать это на сайте за сайтом, поэтому вам нужно только запустить suPHP для скриптов в определенном домене. Мне не хватает опыта, чтобы посоветовать вам, как его установить, но я попросил нашу компанию, специализирующуюся на выделенных серверах, сделать так, чтобы позволить github post-receive hook вызывать скрипт на моем сервере dev для запуска git pull на сервер dev в любое время кто-то подталкивает к репозиторию GitHub. Мне не удалось заставить его работать каким-либо другим способом, поскольку Apache должен работать как владелец локальных репозиториев, чтобы он работал.

Я только что подумал о другом возможном решении, основанном на других комментариях здесь - вы могли бы написать простой скрипт php для получения запроса от ловушки github и записи произвольной информации в файл в каталоге с разрешениями 777 или в БД. Затем запустите задание cron, которое каждую минуту проверяет этот файл или базу данных, чтобы выяснить, изменился ли он, и если да, выполните запрос git pull напрямую, поскольку cron обычно уже выполняется от имени пользователя root. Вы даже можете просто посмотреть, изменилась ли временная метка файла, чтобы определить, нужно ли делать git pull. Вы можете использовать свой cron-скрипт su для любого пользователя, владеющего репозиториями, и затем выполнить git pull. Не настоящее решение в реальном времени, но, если скрипт cron очень прост, он не будет перегружен вашей системой, чтобы вызывать его каждую минуту или две. Надеюсь, это поможет.

0 голосов
/ 18 мая 2016

Я недавно опубликовал проект, который позволяет PHP получать и взаимодействовать с реальной оболочкой Bash (как root, если требуется), он решает ограничения exec () и shell_exec (). Получите это здесь: https://github.com/merlinthemagic/MTS

После загрузки вы просто используете следующий код:

$shell    = \MTS\Factories::getDevices()->getLocalHost()->getShell('bash', true);
$return1  = $shell->exeCmd('/my/bash/script.sh');
//the return will be a string containing the return of the command
echo $return1;

С точки зрения безопасности это гораздо лучше, чем запускать Apache от имени root. Но позволить PHP где-нибудь рядом с root всегда сложно.

Проект, который я создал, достигает оболочки root bash одним из двух способов:

1) Вы разрешаете apache право на sudo python.

OR

2) Вы передаете учетные данные пользователя root каждый раз, когда вам нужна оболочка с настройкой root.

Выбери свой яд. :) Прочитайте документацию.

0 голосов
/ 12 ноября 2014

Используйте демона, работающего от имени пользователя root (возможно, написанного на C), который запускает сценарии оболочки для вас.Чтобы запустить выполнение сценария оболочки из сценария PHP, просто используйте IPC (очереди сообщений).

Посмотрите здесь, чтобы понять, о чем я говорю: http://php.net/manual/en/function.msg-send.php#114831

...