Как я могу заставить скрипт PHP запускать скрипт оболочки от имени root? - PullRequest
2 голосов
/ 06 апреля 2009

Запуск Fedora 9/10, Apache 2, PHP 5 ...

Можно ли запустить сценарий оболочки от имени пользователя root из сценария PHP с помощью exec ()?

Должен ли я просто дать корневые привилегии Apache, а затем добавить команду "sudo" перед ними?

В частности, я пытаюсь запустить и остановить фоновый скрипт.

В настоящее время у меня есть сценарий оболочки, который просто запускает приложение, start.sh:

#!/bin/bash 
/path/to/my/app/appname

И скрипт, который убивает приложение, stop.sh:

#!/bin/bash 
killall appname

Буду ли я просто сделать:

<?php
exec("sudo start.sh");
?>

Заранее спасибо.

Ответы [ 7 ]

13 голосов
/ 06 апреля 2009

Вы не можете просто так использовать sudo, вам нужно сначала настроить sudo без пароля в файле / etc / sudoers. Это можно сделать, например, с помощью команды visudo. Убедитесь, что вы установили привилегии в файле sudoers таким образом, чтобы ограничить пользователя apache той единственной командой, которую вы хотите выполнить (т. Е. Ваш сценарий оболочки).

Даже тогда это создает угрозу безопасности, потому что любой может создать скрипт PHP и запустить скрипт оболочки по очереди. Поэтому убедитесь, что сам скрипт оболочки защищен от изменения пользователем Apache.

Вторая часть, killall , еще более проблематична. Вы не должны просто позволить Apache запускать killall с правами root. Вы должны включить killall в другой скрипт оболочки и предоставить доступ к нему в sudoers.

В конце: не запускайте Apache с учетной записью root и не используйте setuid. Оба открывают банку с червями, и, поскольку вы новичок (учитывая заданный вопрос), вы, скорее всего, пропустите некоторые мелкие детали, которые могут создать потенциальные проблемы.

4 голосов
/ 06 апреля 2009
  1. Не запускайте Apache как root. Apache был спроектирован так, чтобы очень хорошо справляться с запуском как root и затем отбрасывать свои привилегии, как только он может

  2. Также не используйте sudo в вашем скрипте - будет слишком легко в конечном итоге неправильно настроить sudo, так что любой скрипт, работающий на вашем сервере, сможет запустить любую программу с root привилегии

  3. Посмотрите, как заставить вашу собственную программу запускаться "setuid", чтобы она получала привилегии root, но затем отбрасывала их (как это делает Apache), когда они больше не нужны

  4. Убедитесь, что ваш исполняемый файл "setuid" не может быть запущен тем, кто не может его запустить.

3 голосов
/ 06 апреля 2009

Я не профессионал в этой области, но, похоже, вам нужен флаг SUID.

Прочитайте здесь для примеров или Google

2 голосов
/ 30 октября 2012

Вы не хотите давать Apache root.

Есть еще одно решение вашей проблемы. Проблема в том, что Apache не может убить процесс, потому что он принадлежит root. Что вы можете сделать, так это сменить владельца на «www-data», что и идентифицирует Apache.

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

sudo -u www-data <start-up script>

так что www-data будет владельцем этого процесса и, следовательно, будет работать скрипт завершения работы.

2 голосов
/ 06 апреля 2009

Вам нужен слой абстракции, чтобы хотя бы немного обеспечить безопасность! ...

Я могу написать простой UDP-сервер * с правами root на Python, который: следит за входящими пакетами UDP на заданном порту сравнивает их с белым списком если они совпадают, выполнить операцию

Затем у вас есть немного PHP, который отправляет на сервер Python предопределенные сообщения ...

<?php
  $handle = fsockopen("udp://localhost",12345);
  fwrite($handle,"Start Script");
  fclose($handle);
?>

Сервер python отслеживает пакеты на порту 12345, но просто игнорирует все пакеты, которые не являются ни «Start Script», ни «Stop Script», так как он запускается с правами root и может успешно запустить ваш bash-скрипт. Вы АБСОЛЮТНО ДОЛЖНЫ использовать белый список, однако ДЕЙСТВИТЕЛЬНО НЕ БЕЗОПАСНО отправлять ЛЮБОЙ ввод из UDP-сокета в командную строку напрямую!

Обратите внимание, что UDP может быть подделан, поэтому, если ваш брандмауэр разрешает подделанный входящий трафик (это действительно не должно!), Кто-то может отправить поддельные пакеты на ваш сервер Python и остановить / запустить вашу службу. Это вряд ли будет проблемой, но если вы не можете починить свой брандмауэр и хотите защититься от него, вы можете переделать вышеперечисленное, используя TCP / IP, который не может быть подделан.

Роджер Хиткот.

* Это действительно тривиальный сервер для записи (~ 20 строк), но если вы не знаете, как это сделать, просто напишите мне, и я отправлю его вам или опубликую здесь.

1 голос
/ 22 августа 2013

Вы можете использовать ssh-соединение с localhost с аутентификацией keepair для учетной записи, имеющей права root. При такой настройке вам не нужен root-доступ для вашего веб-сервера.

1 голос
/ 07 апреля 2009

По запросу, вот сервер python ...

#!/usr/bin/python
import os 
import socket
print "  Loading Bindings..."
settings = {}
line = 0 
for each in open('/path/to/actions.txt', 'r'):
 line = line + 1
  each = each.rstrip()
  if each <> "":
    if each[0] <> '#':
      a = each.partition(':')
      if a[2]:
        settings[a[0]] = a[2]
      else:
        print "    Err @ line",line,":",each
print "  Starting Server...",
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("", port))
print "OK."
print "  Listening on port:", port
while True:
    datagram = s.recv(1024)
    if not datagram:
        break
    print "Rx Cmd:", datagram
    if settings.has_key(datagram):
      print "Launch:", settings[datagram]
      os.system(settings[datagram]+" &")
s.close() 

Файл конфигурации "actions.txt" использует формат "имя-действия: соответствующая-команда-оболочки", т.е.

# Hash denotes a comment
webroot:nautilus /var/www
ftp:filezilla
edit_homepage:gedit /var/www/homepage/htdocs/index.php

Этот код не проверяет исходный IP-адрес входящих пакетов UDP, так как он работает на локальном хосте, я защищен брандмауэром от кого-либо еще, и проверка в любом случае не обеспечит защиту от спуфинга.

У меня нет времени, чтобы переписать его для использования TCP / IP, но Python - это язык, который стоит узнать, так что если вы действительно хотите эту функциональность, я предоставлю вам Google для Python и 'SOCK_STREAM'. Вероятно, это не стоит ваших проблем, проще настроить брандмауэр, чтобы никакие поддельные пакеты localhost не могли пройти и изменить код, чтобы он прослушивал только пакеты из обратной петли.

...