Существуют ли какие-либо рабочие пакеты для изменения паролей пользователей Linux с помощью PHP?
Я пытался использовать PECL: PAM, но это ошибка при попытке изменить пароль.
Редактировать:
PHP-код:
echo pam_chpass($username, $password, $new_pass, &$error) ? 'good' : $error;
Выход PHP (echo):
Permission denied (in pam_authenticate)
Из / var / log / auth (это на самом деле из-за этого, журнал, похоже, не работает ATM, по какой-то причине еще не определен):
Jun 11 15:30:20 veda php: pam_unix(php:chauthtok): conversation failed Jun 11 15:30:20 veda php: pam_unix(php:chauthtok): password - (old) token not obtained Jun 11 15:30:20 veda php: pam_winbind(php:chauthtok): valid_user: wbcGetpwnam gave WBC_ERR_DOMAIN_NOT_FOUND
Другие:
Извините за отсутствие деталей раньше, я действительно устал, когда я разместил вопрос, но это все еще дерьмовое оправдание.
После нескольких часов исследований в Интернете я не смог найти супер хороший вариант, поэтому я реализовал этот взлом. Он использует эту статью для изменения паролей с помощью PHP.
Я также использую пакет PECL: PAM, чтобы добавить небольшую проверку.
Эта страница находится в безопасной папке HTTPS (автоматическая переадресация через .htaccess)
<?php $messages = array(); function change_password ($user, $currpwd, $newpwd) { // Open a handle to expect in write mode $p = popen('/usr/bin/expect','w'); // Log conversation for verification $log = '/tmp/passwd_' . md5($user . time()); $cmd .= "log_file -a \"$log\"; "; // Spawn a shell as $user $cmd .= "spawn /bin/su $user; "; $cmd .= "expect \"Password:\"; "; $cmd .= "send \"$currpwd\\r\"; "; $cmd .= "expect \"$user@\"; "; // Change the unix password $cmd .= "send \"/usr/bin/passwd\\r\"; "; $cmd .= "expect \"(current) UNIX password:\"; "; $cmd .= "send \"$currpwd\\r\"; "; $cmd .= "expect \"Enter new UNIX password:\"; "; $cmd .= "send \"$newpwd\\r\"; "; $cmd .= "expect \"Retype new UNIX password:\"; "; $cmd .= "send \"$newpwd\\r\"; "; $cmd .= "expect \"passwd: password updated successfully\"; "; // Commit the command to expect & close fwrite($p, $cmd); pclose ($p); // Read & delete the log $fp = fopen($log,r); $output = fread($fp, 2048); fclose($fp); unlink($log); $output = explode("\n",$output); return (trim($output[count($output)-2]) == 'passwd: password updated successfully') ? true : false; } function process_post() { if ((!isset($_SERVER['HTTP_REFERER'])) || (strpos($_SERVER['HTTP_REFERER'], $_SERVER['SCRIPT_NAME']) === FALSE)) { echo "GO AWAY!"; exit(); return FALSE; } global $messages; $username = trim($_POST['username']); $password_current = trim($_POST['password_current']); $password_new = trim($_POST['password_new']); $password_confirm = trim($_POST['password_confirm']); // Check for blanks if ($username == '' || $password_current == '' || $password_new == '' || $password_confirm == '') { array_push(&$messages, "ERROR: You cannot leave any field empty."); return FALSE; } // Check username if (!ctype_alnum($username)) { array_push(&$messages, "ERROR: You've entered an invalid username."); return FALSE; } // Check to see if new password is correctly typed if ($password_new != $password_confirm) { array_push(&$messages, "ERROR: New Password and Confirmation do not match."); return FALSE; } // Check if current password is valid (not really neccessary) if (!pam_auth($username, $password_current, &$error, FALSE)) { if (trim($error) == "Permission denied (in pam_authenticate)") array_push(&$messages, "ERROR: You've username/password was not accepted."); else array_push(&$messages, "ERROR: " . $error); return FALSE; } if (change_password ($username, $password_current, $password_new)) array_push(&$messages, "Password Successfully Changed"); else array_push(&$messages, "ERROR: Password change failed."); } if ($_SERVER['REQUEST_METHOD'] == 'POST') process_post(); ?><html> <head> <title>Passwords</title> <style type="text/css"> body { font-family: Verdana, Arial, sans-serif; font-size: 12px; } label { width: 150px; display: block; float: left; } input { float: left; } br { clear: both; } .message { font-size: 11px; font-weight: bold; } .error { color:#C00; } </style> </head> <body> <h2>Change Passwords</h2> <form action="<?= $_SERVER['SCRIPT_NAME'] ?>" method="post"> <fieldset> <? if (count($messages) != 0) { foreach ($messages as $message) { ?> <p class="message<?= ((strpos($message, 'ERROR:') === FALSE) ? '' : ' error') ?>"><?= $message ?></p> <? } } ?> <label>Username: </label> <input type="text" name="username" /><br /> <label>Current Password:</label> <input type="password" name="password_current" /><br /> <label>New Password:</label> <input type="password" name="password_new" /><br /> <label>Confirm Password:</label> <input type="password" name="password_confirm" /><br /> <input type="reset" value="Reset" /> <input type="submit" value="Submit" /> </fieldset> </form> </body> </html>
У меня также есть этот вопрос / ответ, размещенный в https://serverfault.com/questions/150306/how-to-let-users-change-linux-password-from-web-browser/152409#152409
В дополнение к ответу, отправленному wag2369, обязательно выполните следующие действия:
Установите грушу, которая является менеджером расширений для PHP:
yum install pear
Установите pam-devel из yum
yum install pam-devel
Установите расширение PHP PAM
pecl install --alldeps PAM
–alldeps: средство автоматически устанавливает все зависимости
Измените файл /etc/php.ini
и введите следующее:
extension=pam.so pam.servicename="php"
Для обеспечения службы PAM php выполните следующие действия:
cd /etc/pam.d ln -s login /etc/pam.d/php
Перезапустить apache:
/etc/init.d/httpd restart
/ etc / shadow следует читать (это дыра в безопасности, переосмыслить пожалуйста)
chmod g+r,o+r /etc/shadow
Устанавливать, если они еще не установлены
yum install expect
Исправьте ошибки в коде, отправленном wag2369, или просто скопируйте измененный код ниже: Используйте array_push ($ error, ..) вместо array_push (& $ error, …) 'passwd: пароль обновлен успешно' не должен использоваться, use 'passwd: все токены аутентификации обновлены успешно.' вместо этого проверить.
<?php $messages = array(); function change_password ($user, $currpwd, $newpwd) { // Open a handle to expect in write mode $p = popen('/usr/bin/expect','w'); // Log conversation for verification $log = '/tmp/passwd_' . md5($user . time()); $cmd = ""; $cmd .= "log_file -a \"$log\"; "; // Spawn a shell as $user $cmd .= "spawn /bin/su $user; "; $cmd .= "expect \"Password:\"; "; $cmd .= "send \"$currpwd\\r\"; "; $cmd .= "expect \"$user@\"; "; // Change the unix password $cmd .= "send \"/usr/bin/passwd\\r\"; "; $cmd .= "expect \"(current) UNIX password:\"; "; $cmd .= "send \"$currpwd\\r\"; "; $cmd .= "expect \"Enter new UNIX password:\"; "; $cmd .= "send \"$newpwd\\r\"; "; $cmd .= "expect \"Retype new UNIX password:\"; "; $cmd .= "send \"$newpwd\\r\"; "; $cmd .= "expect \"passwd: all authentication tokens updated successfully.\"; "; // Commit the command to expect & close fwrite($p, $cmd); pclose ($p); // Read & delete the log $fp = fopen($log,'r'); $output = fread($fp, 2048); fclose($fp); unlink($log); $output = explode("\n",$output); return (trim($output[count($output)-2]) == 'passwd: all authentication tokens updated successfully.') ? true : false; } function process_post() { if ((!isset($_SERVER['HTTP_REFERER'])) || (strpos($_SERVER['HTTP_REFERER'], $_SERVER['SCRIPT_NAME']) === FALSE)) { echo "GO AWAY!"; exit(); return FALSE; } global $messages; $username = trim($_POST['username']); $password_current = trim($_POST['password_current']); $password_new = trim($_POST['password_new']); $password_confirm = trim($_POST['password_confirm']); // Check for blanks if ($username == '' || $password_current == '' || $password_new == '' || $password_confirm == '') { array_push($messages, "ERROR: You cannot leave any field empty."); return FALSE; } // Check username if (!ctype_alnum($username)) { array_push($messages, "ERROR: You've entered an invalid username."); return FALSE; } // Check to see if new password is correctly typed if ($password_new != $password_confirm) { array_push($messages, "ERROR: New Password and Confirmation do not match."); return FALSE; } // Check if current password is valid (not really neccessary) $error = ''; if (!pam_auth($username, $password_current, $error, FALSE)) { if (trim($error) == "Permission denied (in pam_authenticate)") array_push($messages, "ERROR: Your username/password was not accepted."); else array_push($messages, "ERROR: " . $error); return FALSE; } if (change_password ($username, $password_current, $password_new)) array_push($messages, "Password Successfully Changed"); else array_push($messages, "ERROR: Password change failed."); } if ($_SERVER['REQUEST_METHOD'] == 'POST') process_post(); ?><html> <head> <title>Passwords</title> <style type="text/css"> body { font-family: Verdana, Arial, sans-serif; font-size: 12px; } label { width: 150px; display: block; float: left; } input { float: left; } br { clear: both; } .message { font-size: 11px; font-weight: bold; } .error { color:#C00; } </style> </head> <body> <h2>Change Passwords</h2> <form action="<?= $_SERVER['SCRIPT_NAME'] ?>" method="post"> <fieldset> <? if (count($messages) != 0) { foreach ($messages as $message) { ?> <p class="message<?= ((strpos($message, 'ERROR:') === FALSE) ? '' : ' error') ?>"><?= $message ?></p> <? } } ?> <label>Username: </label> <input type="text" name="username" value="halaluya" /><br /> <label>Current Password:</label> <input type="password" name="password_current" value="dev0te@m" /><br /> <label>New Password:</label> <input type="password" name="password_new" value="123" /><br /> <label>Confirm Password:</label> <input type="password" name="password_confirm" value="123" /><br /> <input type="reset" value="Reset" /> <input type="submit" value="Submit" /> </fieldset> </form> </body> </html>
Изменение паролей PAM непосредственно из PHP требует большого доступа к вашим системным файлам и службам. Это связано с тем, что по умолчанию PAM использует модуль pam_unix, который хранит учетные данные пользователя в системных файлах, принадлежащих root. Хорошим способом решения этой проблемы является настройка PAM для использования модуля pam_ldap. Таким образом, PAM с аутентифицированными пользователями использует сервер LDAP. Затем с PHP вы можете привязываться к LDAP-серверу с использованием учетных данных пользователя и изменять свой пароль. Авторизация такой модификации может быть решена с помощью механизма авторизации LDAP. (Ваше приложение должно также применять правила авторизации для обеспечения многоуровневой безопасности)
Вышеприведенная конфигурация не является тривиальной. Сначала вы должны настроить LDAP-сервер, а затем перенести все свои пользовательские данные из системных файлов (passwd, shadow) в каталог LDAP. (для этого есть автоматизированные инструменты). И, наконец, вы должны установить и настроить модуль pam_ldap. Любые неправильные конфигурации в вышеуказанном процессе могут привести к серьезным проблемам безопасности.
Также обратите внимание, что таким образом вы будете показывать сервер LDAP в Интернете через ваше приложение. Любые проблемы безопасности, которые могут повлиять на механизмы аутентификации LDAP или авторизации, также повлияют на безопасность вашей системы.
Ресурсы:
Использование LDAP для хранения учетных записей POSIX:
http://www.ibm.com/developerworks/linux/library/l-openldap/
Настройка PAM для использования LDAP для аутентификации:
Существуют ли какие-либо рабочие пакеты для изменения паролей пользователей Linux с помощью PHP?
Это действительно очень опасно. Предполагая, что вы понимаете риски, вы поймете, что вам нужно создать ряд ограничений перед тем, как применить изменения, которые должны быть реализованы на уровне привилегий, который позволяет изменять пароли, то есть код для запуска должен быть автономным исполняемым файлом с либо setuid executoin, либо вызывается через sudo из вашего php-кода.
Конечно, нет причин, чтобы отдельный код не мог быть написан на PHP, кроме того, что (по крайней мере, в последний раз, когда я смотрел на это) привязки PAM в PHP были довольно незрелыми,
Возможно, вам стоит взглянуть на программу chpasswd (доступную на Redhat и некоторые другие дистрибутивы) или использовать proc_open ('/ usr / bin / passwd' … и правильно читать и отвечать на запросы.
НТН
C.
Вы можете использовать пароли RSBAC.
$ret = system("echo \"newpass newpass\" | rsbac_password -n"); if ($ret) echo "fail."; else echo "done!";
Намного проще.