Вопрос или проблема
У меня проблема с выполнением команды, которая требует привилегий root через PHP на сервере Apache
- Я добавил команду в sudoers, чтобы она не требовала пароля для пользователя
visudo:
#
# Этот файл ДОЛЖЕН редактироваться с помощью команды 'visudo' от имени root.
#
# Пожалуйста, рассмотрите возможность добавления локального содержимого в /etc/sudoers.d/ вместо
# прямого изменения этого файла.
#
# Смотрите страницу man для получения подробной информации о том, как написать файл sudoers.
#
Defaults env_reset
Defaults mail_badpass
Defaults secure_path = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# Спецификация псевдонима хоста
# Спецификация псевдонима пользователя
# Спецификация псевдонима команды
# Спецификация привилегий пользователя
root ALL = (ALL: ALL) ALL
# Позволить членам группы sudo выполнять любую команду
%sudo ALL = (ALL: ALL) ALL
# Смотрите sudoers (5) для получения дополнительной информации о директивах "#include":
#includedir /etc/sudoers.d
www-data ALL = NOPASSWD: /sbin/iw
- PHP скрипт, который я пытаюсь выполнить, я также проверяю ошибку, которая возвращается
<? php
echo '<pre>';
$last_line = system('sudo /sbin/iw wlan0 scan 2>&1', $retval);
// Печать дополнительной информации
echo '
</pre>
<hr /> Последняя строка вывода: '. $last_line. '
<hr /> Возвратное значение: '. $retval;
?>
PHP скрипт возвращает
sh: 1: sudo: not found
Последняя строка вывода: sh: 1: sudo: not found Возвратное значение: 127
sudо установлен и работает нормально, когда я выполняю его от другого пользователя
whoami возвращает “www-data”, так что пользователь в порядке
www-data принадлежит к
группе sudo
groups www-data
www-data: www-data sudo
Во-первых, эта строка совершенно неправильная:
www-data ALL = NOPASSWD: /sbin/iw
Если бы вы использовали visudo
для редактирования файла sudoers, вы бы получили предупреждение вроде этого (для номера строки XXX
):
>>> /etc/sudoers: syntax error near line XXX <<<
Это говорит вам о том, что синтаксис неправильный. На самом деле, должно быть так:
www-data ALL = NOPASSWD: /sbin/iw
Однако, отклоняя синтаксис, идея иметь веб-приложение с полным и неограниченным доступом к iw
не кажется хорошей. Обычно подход заключается в том, чтобы написать вспомогательный скрипт, который выполняет одно или два действия, ожидаемых от вызывающего, и ничего больше. Например, если вас интересует только сканирование, не позволяйте скрипту делать что-либо, кроме сканирования. Учетной записи www-data
будут предоставлены права root на этот скрипт, а не на iw
, чтобы даже если кто-то сумеет пробиться через ваше веб-приложение, они могли бы делать только то, что может делать веб-сервер.
Во-вторых, эта строка также неправильная:
last_line = system('sudo /sbin/iw wlan0 scan 2>&1', $retval);
Я не уверен, почему вы считаете, что /sbin/iw
— это содержательная команда, и выполнение этого вызывает ошибку:
sudo /sbin/iw wlan0 scan 2>&1
-bash: syntax error near unexpected token `&'
Используйте правильный синтаксис:
sudo /sbin/iw wlan0 scan 2>&1
В-третьих, вы не говорите, на каком хосте это выполняется, но ваша учетная запись www-data
может не иметь прав доступа к /usr/bin/sudo
. Это сложнее диагностировать без дополнительной информации.
Ответ или решение
Для успешного выполнения скрипта PHP, который требует повышения привилегий до уровня root, необходимо внимательно рассмотреть несколько аспектов работы с sudo
, а также настройки конфигурации вашего сервера и скрипта. Давайте рассмотрим ключевые шаги для решения вашей проблемы.
1. Правильная настройка sudoers
Сначала исправим ошибку в конфигурации файла sudoers
. Ваша текущая запись:
www-data ALL = NOPASSWD: / sbin / iw
содержит пробелы, которые могут вызвать синтаксические ошибки. Правильный синтаксис должен выглядеть следующим образом:
www-data ALL = NOPASSWD: /sbin/iw
Кроме того, важно учитывать, что предоставление команде iw
прав root без ограничения — это потенциально уязвимо. Вместо этого рекомендуется создать вспомогательный скрипт, который будет выполнять только те команды, которые действительно нужны, оставляя место для контроля.
2. Создание вспомогательного скрипта
Рассмотрим создание скрипта, который будет выполнять специфические команды. Создайте файл /usr/local/bin/iwscan.sh
и предоставьте необходимые права:
sudo touch /usr/local/bin/iwscan.sh
sudo chmod 755 /usr/local/bin/iwscan.sh
Отредактируйте скрипт:
#!/bin/bash
/sbin/iw wlan0 scan
Теперь внесите изменения в sudoers
, чтобы предоставить доступ только к этому скрипту:
www-data ALL = NOPASSWD: /usr/local/bin/iwscan.sh
3. Обновление PHP скрипта
Теперь нужно изменить ваш PHP-скрипт, чтобы он вызывал этот вспомогательный скрипт. Вот как будет выглядеть обновленный код:
<?php
echo '<pre>';
$last_line = system('sudo /usr/local/bin/iwscan.sh 2>&1', $retval);
// Печать дополнительной информации
echo '</pre><hr />Последняя строка вывода: ' . $last_line . '<hr />Возвращаемое значение: ' . $retval;
?>
4. Проверка прав доступа
Также убедитесь, что пользователь www-data
действительно имеет доступ к sudo
и к командному интерпретатору. Проверьте это, выполнив:
sudo -l -U www-data
Это должно показать вам, что www-data
может выполнять /usr/local/bin/iwscan.sh
без ввода пароля.
5. Другие причины ошибок
Если все вышеперечисленное правильно настроено, а ошибка sh: 1: sudo: not found
все равно возникает, возможно, существует ошибка в пути sudo
. Обычно sudo
находится в /usr/bin/sudo
. Убедитесь, что этот путь доступен для пользователя www-data
, выполняя:
which sudo
Заключение
Следуя вышеперечисленным шагам, вы сможете запустить iw
с правами root через PHP, одновременно соблюдая меры безопасности. Лучше всего ограничить сеть привилегий только тем действиям, которые необходимы, и избегать запуска опасных команд от веб-пользователей. Убедитесь, что тестируете все изменения на вашем сервере, чтобы выявить и исправить любые дополнительные проблемы.