PHP/PAM更改用户密码?
是否有任何工作包使用PHP更改linux用户密码?PHP/PAM更改用户密码?
我试过使用PECL:PAM,但当它尝试更改密码时发生错误。
编辑:
PHP代码:
echo pam_chpass($username, $password, $new_pass, &$error) ? 'good' : $error;
PHP(回波)输出:
Permission denied (in pam_authenticate)
在/ var /日志/ AUTH(这些是实际从之前,日志没有按“T似乎工作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
其他:
对不起,以前缺乏细节,当我发布这个问题时,我真的很累,但那仍然是一个糟糕的借口。
afte在线研究小时,我无法找到一个超好的选择,所以我实施了这个黑客攻击。它使用this article来更改使用PHP的密码。
我还使用了PECL:PAM package增添了几分验证。
这页是安全的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 \"[email protected]\"; ";
// 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
请仔细阅读下面的注释,以便能够正确配置PAM,并处理尝试运行上述代码时可能遇到的所有问题。 – 2011-03-02 07:41:49
这两个版本的脚本都要求要更改密码的用户拥有有效的shell。由于使用'su'脚本不适用于具有禁用shell的用户。 – xebeche 2013-11-20 22:08:27
是否有任何工作包改变了使用PHP的Linux用户的密码?
这是真的,真的很危险。假设你了解风险,那么你会意识到,在应用必须在允许更改密码的权限级别中实现的更改之前,您需要构建一些约束 - 即运行此代码的代码必须是独立的可执行文件无论是setuid executoin还是通过你的php代码通过sudo调用。
当然,没有理由不能用PHP编写独立的代码,除了(至少,最后一次看这个)PHP中的PAM绑定的事实还不成熟,
你可能想看看chpasswd的程序(可在红帽和其他一些发行版),或使用proc_open(“的/ usr/bin中/ passwd文件” ......和阅读并提示正确响应。
HTH
C.
我在找东西,以便用户可以更改自己的密码。它不会使用自己的用户权限来尝试登录和密码更改吗? – wag2639 2010-06-14 03:26:12
Erk!如果你不明白为什么这不起作用,那么你可能不应该搞砸它,除非你已经阅读了更多关于认证和许可如何在posix系统上工作的内容。而且您不得允许基于Web的表单更改密码所需的权限。编写webmin的人是有能力的程序员 - 他们错误地多次错了。只有root可以改变他人的密码。要更改自己的密码,它仍然需要以root身份启动,然后seteuid()。 – symcbean 2010-06-14 10:33:23
然后我想我会用proc_open去。我只是减少了一个更好的检查。 – wag2639 2010-06-15 02:43:50
你可以使用RSBAC密码。
$ret = system("echo \"newpass newpass\" | rsbac_password -n");
if ($ret)
echo "fail.";
else
echo "done!";
这么容易多了。
除了张贴wag2369答案,一定要执行以下操作:
安装梨是PHP的扩展管理器:
yum install pear
从百胜
安装PAM-devel的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或只是在代码中的bug复制下面的修改后的代码: '不应使用'passwd:password updated successfully',使用 '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 \"[email protected]\"; ";
// 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="[email protected]" /><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>
对于php.ini设置和chmod,这篇文章是我在互联网上搜索过的最详细的文章。 – 2017-05-11 10:13:18
直接从PHP更改PAM密码需要多次访问您的系统文件和服务。这是因为PAM默认使用pam_unix模块,该模块将用户凭证存储在由root拥有的系统文件中。解决此问题的一个好方法是设置PAM以使用pam_ldap模块。这种PAM方式使用LDAP服务器对用户进行身份验证。然后从PHP中,您可以使用用户凭据绑定到LDAP服务器并更改密码。授权这种修改将由LDAP授权机制来处理。 (您的应用程序还应该执行授权规则,以提供分层的安全性)
上述配置不是微不足道的。您必须先设置LDAP服务器,然后将所有用户数据从系统文件(passwd,shadow)迁移到LDAP目录。 (有自动化工具)。最后,您必须安装并设置pam_ldap模块。上述过程中的任何错误配置都可能导致严重的安全问题。
请注意,通过这种方式,您将通过您的应用程序将LDAP服务器公开到Web上。任何可能影响LDAP认证或授权机制的安全问题也会影响您的系统安全。
资源:
使用LDAP存储POSIX帐户:
http://www.ibm.com/developerworks/linux/library/l-openldap/
设置PAM使用LDAP进行身份验证:
您提到有自动工具转移到LDAP。你有链接到那些? – Azmisov 2014-08-08 20:17:38
“那里有一个错误,当它试图更改密码“ - 什么错误?你刚刚去了医生办公室,告诉他“疼,”但不会告诉他在哪里。 – Charles 2010-06-13 20:54:24