nixCraft Poll

Topics

Change Linux or UNIX system password using PHP script

Posted by Vivek Gite [Last updated: April 10, 2008]

If you just wanted to change your own password or other user passwords use passwd command.

I was asked to setup a PHP based interface to change the password. Since my knowledge of php is limited. Here is what I did:

Required tools/setup:

You must have following tools/software installed

=> Shell script to change password

=> Sudo access

=> Apache or Lighttpd web server

=> PHP server side

Step # 1: Setup a shell script to change password

This shell script use expect tool to change the password (see more about expect tool here).

Sample shell script code

#!/bin/sh
# \
exec expect -f "$0" ${1+"$@"}
set password [lindex $argv 1]
spawn passwd [lindex $argv 0]
sleep 1
expect "assword:"
send "$password\r"
expect "assword:"
send "$password\r"
expect eof

You can execute this script as follows (dowload link):
$ chpasswd username password

Download script and copy to your webroot or location where webserver can read this script file:
$ cp chpasswd /var/www/

ALTERNATIVELY, if you are using Ligtttpd web server:
$ cp chpasswd /home/lighttpd

Step # 2: Setup sudo to execute a command as root user

Apache or Lighttpd web server drops root privileges as soon as they go into background. This makes changing password scenario difficult as passwd command needs root privileges to change other user account password.

Typically, Apache 2 use www-data user and Lighttpd use lighttppd username to drop privileges. Login as root user and type the following command:
# visudo

Now allow your web server to execute a script (chpasswd) w/o password. If you are using Apache web server, type the following command:
www-data ALL=NOPASSWD: /var/www/chpasswd

ALTERNATIVELY, if you are using Ligtttpd web server, type the following command:
lighttpd ALL=NOPASSWD: /home/lighttpd/chpasswd

Save and close the file.

Step # 3: Create a PHP based interface

Now you need to write a php script. Here is sample php script. This is a demo script. You should modify it according to your requirement or setup. At minimum, you need to setup correct shell script location so that it will work for you out of box. Open php script and locate line:
$shellscript = "sudo /home/lighttpd/chpasswd";

Change it to point to correct location. PHP Source code:

<?php
// change .. me! - shell script name
$shellscript = "sudo /home/lighttpd/chpasswd";
 
// Make sure form is submitted by user
if(!(isset($_POST['pwdchange']))) {
 // if not display them form
 writeHead("Change password");
 writeForm();
 writeFoot();
}
else {
 // try to change the password
 $callshell=true;
 // get username and password
 $_POST['username'] = stripslashes(trim($_POST['username']));
 $_POST['passwd'] = stripslashes(trim($_POST['passwd']));
 
// if user skip our javascript ...
// make sure we can only change password if we have both username and password
 if(empty($_POST['username'])) {
   $callshell=false;
 }
 if(empty($_POST['passwd'])) {
   $callshell=false;
 }
 if ( $callshell == true ) {
  // command to change password
  $cmd="$shellscript " . $_POST['username'] . " " . $_POST['passwd'];
  // call command
  // $cmd - command, $output - output of $cmd, $status - useful to find if command failed or not
   exec($cmd,$output,$status);
   if ( $status == 0 ) { // Success - password changed
   writeHead("Password changed");
   echo '
<h3>Password changed</h3>
 
Setup a <a href='. $_SERVER['PHP_SELF'] . '>new password</a>';
   writeFoot();
   }
   else { // Password failed
      writeHead("Password change failed");
      echo '
<h3>Password change failed</h3>
 
';
      echo '
 
System returned following information:
 
';
      print_r($output);
      echo '
 
<em>Please contact tech-support for more info! Or try <a href='.$_SERVER['PHP_SELF'].'again</a></em>
 
';
      writeFoot();
   }
 }
 else {
   writeHead("Something was wrong -- Please try again");
   echo 'Error - Please enter username and password';
   writeForm();
   writeFoot();
 }
}
 
// display html head
function writeHead($title) {
echo '
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title> ' .$title. '</title>
<style type="text/css" media="screen">
.passwdform {
	position: static;
	overflow: hidden;
}
 
.passwdleft {
	width: 25%;
	text-align: right;
	clear: both;
	float: left;
	display: inline;
	padding: 4px;
	margin: 5px 0;
}
 
.passwdright {
	width: 70%;
	text-align: left;
	float: right;
	display: inline;
	padding: 4px;
	margin: 5px 0;
}
 
.passwderror {
	border: 1px solid #ff0000;
}
 
.passwdsubmit {
}
</style>
 
</head>
 
<body>';
 
}
// display html form
function writeForm() {
echo '
<h3>Use following form to change password:</h3>
 
<script>
function checkForm() {
if (document.forms.changepassword.elements[\'username\'].value.length == 0) {
    alert(\'Please enter a value for the "User name" field\');
    return false;
}
if (document.forms.changepassword.elements[\'passwd\'].value.length == 0) {
    alert(\'Please enter a value for the "Password" field\');
    return false;
}
  return true;
}
</script>
<div class="contactform">
<form action="' . $_SERVER[PHP_SELF]. '" method="post" onSubmit="return checkForm()" name="changepassword">
<div class="passwdleft"><label for="lblusername">User Name: </label></div>
<div class="passwdright">
<input type="text" name="username" id="lblusername" size="30" maxlength="50" value="" /> (required)</div>
<div class="passwdleft"><label for="lblpasswd">Password: </label></div>
<div class="passwdright">
<input type="password" name="passwd" id="lblpasswd" size="30" maxlength="50" value="" /> (required)</div>
<div class="passwdright">
<input type="submit" name="Submit" value="Change password" id="passwdsubmit" />
<input type="hidden" name="pwdchange" value="process" /></div>
</form>
</div>
 
';
 
}
// display footer
function writeFoot(){
echo '</body>
</html>
';
}
?>

Step # 4: Run the script

Point a web browser to your server url - https://mydomain.com/changepassword.php. You should see a username and password form as follows:

changepassword php script output # 1

If a password is changed successfully, you should get confirmation as follows:

changepassword php script output # 2

For some reason if a password failed to change, you should get detailed error message as follows:

changepassword php script output # 3

Step # 5: Security

Note this is an example and not final solution as it is little insecure.

Want to stay up to date with the latest Linux tips, news and announcements? Subscribe to our free e-mail newsletter or RSS feed to get all updates. You can Email this page to a friend.

You may also be interested in other helpful articles:

Discussion on This Article:

  1. prem Says:

    why we need this much pain you can use webmin for easy configuration or some other tools to do this

  2. nixcraft Says:

    Ready to use tools or webmin are not useful for custom-made control panel or other solution. Every situation is different hence; you need to develop your own methods.

    No, it is not a pain. We simply call it hacks :P

  3. pipacs Says:

    The expect script proposed here is extremely dangerous. Any user monitoring commands with “ps” could capture user names and passwords.

  4. nixcraft Says:

    Pipacs,

    Thanks for your concern. I agree with you. At the movement, this box can be access by admins only and other user change password using above solution.

    But if you need to give shell access -
    On FreeBSD with secure runlevel prevents other users from monitoring command/script arguments from ps, w, who, top etc commands.

    On Linux system you need to apply a special patch to kernel (LINUX BSD LSM) or disable other user shell login all together

    If you have any other, solution then please let me know…

    Appreciate your post.

  5. chadrick Says:

    Hey, any idea why the expect scriptscript does not works if i remove sleep 1 command :/?

  6. nixcraft Says:

    Chadrick,

    As name, suggest sleep command puts pause for NUMBER seconds (1 second). If you are using Debian Linux you need to use sleep to slow down few things. However, on RHEL or CentOS or FreeBSD it works w/o sleep command.

  7. Sven Says:

    passing the POST data straight to a shell is also dangerous. a semicolon in either field, and everything else is executed as a separate command..

    See:
    http://www.php.net/manual/en/function.escapeshellcmd.php
    http://www.php.net/manual/en/function.escapeshellarg.php

  8. Boo Says:

    So, uh, I can just change anyone’s password that I want to? Am I missing something?

    username: root
    password: owned

    Shouldn’t you also at least use SSL or something?

  9. nixcraft Says:

    @Boo, you ssl and Password protected directory is must

    @Sven, thanks for link i will update my code!

    As I said earlier, my knowledge of php is limited. At the movement, script is protected using SSL and a password-protected directory.

    And I must add protection for root user… in php itself

    Appreciate all of your posts.

  10. dean Says:

    I am very interested in doing this for a new production process.

    Is it possible to have the current password vierified first?

  11. Lars Says:

    thx for the script, very close what i needed quick-and-dirty here, got it up and running for my purpose within 10 minutes.

    And yep, its extremely dangerous, but the box running it isn’t designed to be overly safe or even public anyway ^^

  12. elton Says:

    I am getting the following error:

    spawn passwd
    passwd: Only root can specify a user name.

    Which makes sense, but how did you not get this?

  13. nixcraft Says:

    You need give web server user to change password permission using sudo tool (see step # 2).

  14. Chris Says:

    How can I change this script to add new users ?

  15. nixcraft Says:

    Yes you can. You write a shell script and call same way.

  16. elvis Says:

    As written, this script allows any user’s password to be changed, which may not be a good thing. By placing this script in a secure, password-protected directory, you can avoid having to request the username on the form & instead use the $_SERVER['PHP_AUTH_USER'] variable to get the name of the currently-authenticated user. That will restrict password changes to the authenticated user only.

  17. nixcraft Says:

    elvis,

    Good suggestion. I will try to implement them. Yes currently script runs in password protected directory over ssl session.

    Appreciate your post.

  18. Fer Says:

    hi,
    thank you for sharing your code with us.i want to do the samething but i have to confirm the password first.And this is not working at this point.I think confirming password first needs to edit the shell script at step one.And i dont know about shell scripts.If you have a solution for this problem or anyone knows,please share with us.
    thank you again

  19. Ahmad Says:

    what we have to do if we want script to match old password first then allow to change the password

  20. jose alfredo Says:

    it doesn`t work on my server,
    i keep getting this error message and nothing works whenever i try to print the output array, i get nothig just “Array”, can you help me debug this, sorry about my french

  21. nixcraft Says:

    If you see an array that mean shell script is not working properly. You need to setup correct permission using sudo. What distor and webserver you are using?

  22. jose alfredo Says:

    i am using httpd 2.0.52-22 on a CentOS 4 and i gave both apache and www-data permission to run da script and passwd, but i keep getting nothig but “Array
    (
    )

  23. Jay Dingenen Says:

    I’m having a problem with this script, sometimes if i execute it, it doesn’t return “passwd: all authentication tokens updated successfully.” but i can’t check this from my php so the password isn’t updated and my clients can’t use their ftp logins…
    Is it possible to like expect “successfully.” or else restart the script? I haven’t got a clue how to do this so all ideas are welcome.

  24. Herb Perkins-Frederick Says:

    Thanks!

    I have a serer running Fedora Core 3. I was having problems with an expect script that I wrote, so I found your site. The chpasswd script worked with one minor modification: instead of “\r” an the end of the send lines, it wanted “\r\n” on my system.

    Thanks again!
    Herb

  25. Alex Says:

    My system is Redhat Linux9.
    I try to execute chpasswd script to change password.
    But the script didn’t change password successfully.

    And I try to open the PHP file.
    After I input username and password that also display error message.

    =========
    Password change failed
    System returned following information…..:

    Array
    (
    )

    Please contact tech-support for more info! Or try

    =========
    What can I do and resolve his problem?

  26. שדרך Says:

    Alex,

    Try putting the full path to sudo in the php script, that fixed the problem for me:

    /usr/bin/sudo

  27. Matt Says:

    I am having the same problem as Alex and I have the full path to sudo in my php script. Any clue?

  28. Matt Says:

    I had to hardcode the command in the $cmd to get it to work

  29. Dan Says:

    Give http://changepassword.sourceforge.net/ a try.

  30. vivek Says:

    Dan,

    Good finding.

    Appreciate your posts!

  31. Fabian Says:

    Hello
    I got this error when I try to run the php script

    Parse error: parse error, unexpected T_STRING, expecting ‘,’ or ‘;’ in /srv/www/htdocs/changepassword.php on line 108

    here you have line 108
    if (document.forms.changepassword.elements['username'].value.length == 0) {

    Thanks for your help

  32. Mark Says:

    Fabian — Don’t copy&paste from the site, but use the linked PHP file.

    My own question is; where the heck is this spawn command located?! :)

  33. daphne Says:

    Couldn’t get this to work using Apache or Lighttpd.

    when I browser to localhost://changepassword.php
    it just shows a text file of changepassword.php.

    Am I doing something wrong?

  34. Sergei Says:

    Dan, http://changepassword.sourceforge.net/ has 35 open bugs and has been abandoned for couple of years now. I think I will stick with Vivek’s scripts

  35. tekhawk Says:

    Could something like this be used on mac server os x as a web based user password reset tool?

  36. Eric Says:

    I’m new to PHP, so don’t expect this to be perfect. It gives me a parse error with the following (very simple) code:

    I’m using this to scare the guys in the server room (where we have a Mac Pro).

    I don’t even think the syntax is correct either…

  37. Eric Says:

    Why isn’t my code showing?

  38. Steve Says:

    This solution involves giving the web user full control over a script that can change any system user’s password, without verification. You might as well just run apache as root.

  39. Liberty Dandira Says:

    Alternatively, without including the shell script

    after visudo

    Replace www-data ALL=NOPASSWD: /var/www/chpasswd

    with

    www-data ALL=NOPASSWD: ALL

    in your PHP script

    just enter

  40. Vijay Says:

    Hello everyone,

    I need to know how to change linux system time zone using php script.

    used this in shell,that is
    $ export TZ=MST, then timezone changed to MST,
    but i tried this using php script,
    that is,

    but this is not working.
    can anyone tell me what is the reason for this

  41. JimmyJam Says:

    When I run the PHP script, I get
    sudo: unable to execute /var/www/chpasswd: No such file or directory

    My /etc/sudoers contains the following entry
    www-data ALL=NOPASSWD: /var/www/chpasswd

    I have tested this with permission on /var/www/chpasswd set to 744 and 777 but with no luck.

    I call the script from PHP using the following:

    // set the user's password
    $command = 'sudo /var/www/chpasswd'.
    $user_info['username'].’ ‘.
    $user_info['password'];
    shell_exec($command);

    Any help would be greatly appreciated

  42. Tomek Gruca Says:

    pipacs: “The expect script proposed here is extremely dangerous. Any user monitoring commands with “ps” could capture user names and passwords.”

    instead of executing “$ chpasswd username password” you can save the password in a tmp file, unreadable for users - that’s what I’ll do ;)

    Great script!

  43. Turn fun Says:

    good tool for web server admins ! :)

  44. kevin_cn Says:

    hello
    is anyone luck enough?
    i have the same problem with 25f’s Alex on arch 27th, 2007 at 7:33 am
    i am new to php ,how could i do?
    please help!

Leave a Reply

We encourage your comments, and suggestions. But please stay on topic, be polite, and avoid spam. Thank you very much for stopping by our site!

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word

Tags: , , , , ,

Copyright © 2004-2008 nixCraft. All rights reserved - TOS/Disclaimer - Privacy policy - Sitemap - Powered by Open source software.