Выполнять команды root через PHP - PullRequest
49 голосов
/ 16 декабря 2011

У меня есть сервер CentOS 5.7 linux и я использую php5.3.x.

В системе pfSense вы можете перезапускать службы, для которых требуются права root, с помощью веб-страницы php.

Я пытаюсь сделать что-то подобное, я написал PHP-код для выполнения команд оболочки.Например, чтобы перезапустить службу sshd:

<?php
exec('/sbin/service sshd restart');
?>

, и я попытался выполнить эту команду с помощью функции exec, но для этого требуется разрешение root, но у нас есть полномочия пользователя apache.

Iнаткнулся на несколько решений:

  1. «запускать apache с пользователем root» действительно небезопасно.Я не хочу этого делать.
  2. "apache ALL = NOPASSWD: / sbin / service to / etc / sudoers" Я пытался, но у меня все еще есть проблема.

Любая другаярешения?Спасибо за ответы.


сейчас .. это интересно.я попробовал @refp post, и это сработало на моем локальном сервере Ubuntu.Но когда я попробовал то же самое на моем VOS-сервере CenOS.Это не работает. И это журнал ошибок apache "rm: не удается удалить` / var / lock / subsys / vsftpd ': разрешение отклонено "

Ответы [ 5 ]

89 голосов
/ 16 декабря 2011

Прочитайте весь этот пост, прежде чем попробовать, есть варианты выбора.


Решение с использованием двоичной обертки (с битом suid)

1) Создайте сценарий (предпочтительно .sh), содержащий то, что вы хотите запустить от имени пользователя root.

# cat > php_shell.sh <<CONTENT
  #!/bin/sh
  /sbin/service sshd restart
CONTENT

2) Этот файл должен принадлежатьот имени пользователя root, и, поскольку он будет позже запускаться с правами root, убедитесь, что только root имеет разрешение на запись в файл.

# chown root php_shell.sh
# chmod u=rwx,go=xr php_shell.sh

3) Запускать скрипт от имени пользователя root не имеет значенияпользователю, который его выполняет, нам понадобится двоичная оболочка.Создайте тот, который будет выполнять наши php_shell.sh.

# cat > wrapper.c <<CONTENT
  #include <stdlib.h>
  #include <sys/types.h>
  #include <unistd.h>

  int
  main (int argc, char *argv[])
  {
     setuid (0);

     /* WARNING: Only use an absolute path to the script to execute,
      *          a malicious user might fool the binary and execute
      *          arbitary commands if not.
      * */

     system ("/bin/sh /path/to/php_shell.sh");

     return 0;
   }
CONTENT

4) Компилировать и устанавливать правильные разрешения, включая бит suid (говоря, что он должен работать с привилегиями root):

# gcc wrapper.c -o php_root
# chown root php_root
# chmod u=rwx,go=xr,+s php_root

php_root теперь будет работать с правами суперпользователя и выполнять команды, указанные в php_shell.sh.


Если вам не нужна опция для простого изменения командэто будет выполнено, я бы порекомендовал вам писать команды непосредственно в wrapper.c на шаге 4 .Тогда вам не нужно иметь двоичный файл, выполняющий внешний скрипт, выполняющий рассматриваемые команды.

В wrapper.c используйте system ("your shell command here");, чтобы указать, какие команды вы хотите выполнить.

22 голосов
/ 16 декабря 2011

Я бы не стал выполнять PHP-команды sudo. Для меня это звучит как просьба о неприятностях. Вместо этого я бы создал две отдельные системы.

Первая система на PHP (веб-уровень) будет обрабатывать запросы пользователей. Когда делается запрос, требующий команды sudo, я помещаю этот запрос в какую-то очередь. Это может быть база данных какого-либо рода или промежуточное программное обеспечение, такое как ZeroMQ.

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

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

8 голосов
/ 04 января 2016

Разрешить пользователю www-data запускать program1 и program2 без пароля:

sudo visudo

Добавить в содержимое файла sudoers:

User_Alias WWW_USER = www-data
Cmnd_Alias WWW_COMMANDS = /sbin/program1, /sbin/program2
WWW_USER ALL = (ALL) NOPASSWD: WWW_COMMANDS

Сохранить.

от https://askubuntu.com/questions/76920/call-a-shell-script-from-php-run-as-root

2 голосов
/ 14 февраля 2018

Решение с использованием двоичной обертки (с битом suid) Некоторая модификация Filip Roséen - refp post.

Для выполнения любой команды изменен wrapper.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

int main (int argc, char  **argv)
{
 setuid (0);
 char cmd[100] = "";
 int i;
 char *p;
 for(i=0; i < argc; i++) {
    if(i != 0){
   strcat(cmd, *(argv+i));
   strcat(cmd, " ");
    }
 }

 system (cmd);

 return 0;
 }

Скомпилируйте и установите правильные разрешения;

  gcc wrapper.c -o php_root     # php_root can be any name.
  chown root php_root
  chmod u=rwx,go=xr,+s php_root

Теперь звоните из PHP.Выполнить любую команду.

 shell_exec('./php_root '.$cmd);//execute from wrapper
2 голосов
/ 17 мая 2016

Я недавно опубликовал проект, который позволяет PHP получать и взаимодействовать с реальной оболочкой Bash, он легко даст вам оболочку, вошедшую в систему как root. Затем вы можете просто выполнить отдельные команды bash, а не связывать их в сценарии. Таким образом, вы также можете обрабатывать возврат. Получите это здесь: https://github.com/merlinthemagic/MTS

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

$shell    = \MTS\Factories::getDevices()->getLocalHost()->getShell('bash', true);
$return1  = $shell->exeCmd('service sshd restart');

echo $return1;

//On CentOS 7 output would be like: 
//Redirecting to /bin/systemctl restart  sshd.service

//On CentOS 6 and lower output would be like:
//Stopping sshd:                                             [  OK  ]
//Starting sshd:                                             [  OK  ]
...