Изменить пароль пользователя Linux из PHP-скрипта

У меня есть «простой» вопрос: как я могу безопасно изменить пароль пользователя из скрипта PHP, не предоставляя привилегии суперпользователя Apache или вводя другие сумасшедшие дыры в безопасности?

Фон: CentOS 6, Apache 2.2.13, PHP 5.3.3

Я знаю о команде pam_chpasswd(), которая является частью библиотеки PECL PAM. Однако эта функция не работает, если хост-процесс (httpd) не имеет доступа для чтения к файлу /etc/shadow. (ПЛОХАЯ ИДЕЯ! Не уверен, как эта библиотека поможет, если она требует таких высоких привилегий...)

Идеальная ситуация, насколько я вижу, состоит в том, чтобы PHP вызывал сценарий оболочки с помощью «sudo -u [имя пользователя, меняющего свой пароль]». Это запустит сценарий «КАК» пользователь, поэтому он должен иметь разрешение на изменить собственный пароль. И sudo потребует, чтобы пользователь отправил свой существующий пароль для аутентификации, что не позволит одному пользователю изменить пароль другого пользователя.

Но по какой-то причине это не работает... при открытии процесса с помощью popen процесс никогда не выполняется. У меня есть сценарий оболочки, настроенный на вывод некоторого текста в общедоступный файл для записи в /tmp. Но до этого никогда не доходит.

$cmd = "/usr/bin/sudo -S -u$username /file_to_execute.sh";
$handle = popen ($cmd, "w");   // Open the process for writing
fwrite ($handle, "$current_password\n");  // Send the user's current password to sudo (-S option)
fwrite  .... (write the username, current password, and new password, so the script can change it)
$result = pclose($handle);

Если я получу доступ к этому php-скрипту (http://server/script.php), функция немедленно завершится ошибкой, и $result = 1

Если я изменю файл sudoers (visudo) и добавлю строку:
$Defaults:apache !requiretty

Скрипт зависает примерно на 10 секунд, затем завершается сбоем ($result = 1)

Любые предложения по этому поводу приветствуются!


person Ryan Griggs    schedule 24.07.2012    source источник
comment
Что-нибудь из этого работает? stackoverflow.com/questions/127459/   -  person aknosis    schedule 24.07.2012


Ответы (2)


Чтобы достичь вышеизложенного с учетом безопасности, я бы предложил либо использовать expect, либо добавить пользователя Apche в группу, у которой есть доступ на запись к указанному файлу и только к указанному файлу.

Ожидается, что вам нужно будет указать свой пароль sudo, так как он будет прослушивать ответ от ОС Password:, и когда его увидят, он автоматически ответит паролем sudo. Это позволит вам объединить shell_exec() и семью с expect для достижения ваших результатов.

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

Пример:

groupadd secure_apache
usermod -G secure_apache apache_user
chown owner:secure_apache /tmp/file_to_change
chmod 740 /tmp/file_to_change
person Mike Mackintosh    schedule 24.07.2012
comment
Будет ли №2 работать в многопользовательской среде? т.е. несколько пользователей одновременно пытаются изменить свои пароли? Я предполагаю, что каждый запрос на смену пароля должен создавать файл со случайным именем, чтобы пользователи не наступали друг на друга во время процесса...? - person Ryan Griggs; 24.07.2012
comment
Если вы выберете второй вариант, вы можете реализовать flock() для блокировки файла при попытке первого пользователя. КОГДА они будут завершены, удалите flock(), и другие пользователи смогут уйти. По крайней мере, другие пользователи получат сообщение об ошибке, говорящее о невозможности в это время. - person Mike Mackintosh; 24.07.2012
comment
Мне никогда не удавалось popen получить доступ к STDIN из sudo. Однако взгляните на это. пароль пользователя"> stackoverflow.com/questions/127459/ - person Mike Mackintosh; 24.07.2012

Более безопасный способ сделать это — сохранить имя пользователя и пароль в файле в специальном каталоге и позволить cron выполнять эту работу (раз в минуту).

person Ron    schedule 24.07.2012
comment
Спасибо за Ваш ответ. Однако это создает 2 проблемы: 1) Пользователь не может получить немедленную обратную связь о том, был ли изменен его пароль. 2) Существующий пароль пользователя не проверен. Похоже, это может быть не слишком безопасно. Я хочу, чтобы пользователь должен был указать свой существующий пароль, чтобы изменить пароль. Это предотвращает любой тип захвата одним пользователем для изменения пароля другого пользователя. - person Ryan Griggs; 24.07.2012