I started a thread a while back asking for suggestions on a good (good=fairly secure) way to allow users to change their account passwords via a PHP script. (WHY? because on this particular server, I have a lot of email-only users with no shell access who need to be able to change their passwords without asking me to do it for them.)

The few answers given didn't really help. I don't want to dump passwords in a file, or do some sort of batch update every x seconds. It needs to be an immediate, thread-safe system which 1) requires that the user verify his existing password, and 2) changes password immediately (no batching).

So I created an executable utility and a small PHP script to accomplish this. I am submitting these here for review, in hopes the community can point out things I did wrong/ways in which this can be vulnerable to attack, and in hopes it will help someone else.

Config info: The 'chpwd' utility is set to run SUID root - required for access to the /etc/shadow file. I can't see any way around this. Note that the actual "change password" code which accesses the /etc/shadow file is copied directly from the source of the 'passwd' utility.

The chpasswd.php script runs with standard permissions on the web server.

Here is the example code:

chpwd.c: http://chopapp.com/#rghbyc9x

chpasswd.php: http://chopapp.com/#iedg9x60

Thank you in advance for all constructive criticism and suggestions.

  • 2
    Yes this is very obviously remote code execution. Worse idea ever. Voting to close. – rook Dec 18 '12 at 21:03
  • @Rook Glad to see I'm not the only one that cringed. – Polynomial Dec 18 '12 at 23:50
  • 1
    If piping to another utility, why not pipe not passwd that is already installed? Not that it is a sensible idea in the first place, why not use a proper separate email database? You don't think google create system accounts for every gmail account do you? – ewanm89 Dec 19 '12 at 1:16
  • @Rook - I don't understand why, in a "security forum" you would vote down a question about how to make something more secure? Yes, maybe it is an insecure way of doing this, so please try to be helpful instead of bashing me. I.e. WHY is it insecure, HOW could it be done better/differently? If you don't feel like answering the question, why bother with a reply that doesn't help? I am actually trying to learn something here. – Ryan Griggs Dec 19 '12 at 3:46
  • @ewanm89 - Thank you for your comment. You actually answered my question better than any other comment so far: I should have used a DATABASE instead of using system accounts for email-only users! That's why I asked question: seeking constructive, out-of-my-box answers, and yours fits the bill. Now, I will stop worrying about changing passwords on system accounts and focus on learning how to implement a back-end database with Postfix. THANK YOU for providing helpful info! Please post this in an actual Answer and I will choose it as the best answer. – Ryan Griggs Dec 19 '12 at 3:51

/me takes a deep breath

First lets start with the concept. This is a bit suspect. getting users to remember a password they use every day is hard enough - if they use a MUA which remembers their password for them this is not going to save you any time/effort.

Next question is why are you reinventing the wheel? chpasswd comes with most versions of Linux and some Unix, and the source code is freely available. Further, unlike your code it correctly uses PAM to manipulate the authentication tokens appropriately. Or even just using passwd to handle the operation (the latter requires an expect script wrapper or PHP control, while both approaches would use sudo or could be invoked over an ssh session authenticated against the supplied username/old password).

But even if you're never going to change your authentication backend nor your encryption algorithms and you're not bothered about bypassing the policy controls (such as locked/expired accounts) and are quite happy to completely short out PAM why are you implementing your own parser for the code instead of using using the getpwent/setpwent functions?

| improve this answer | |
  • 1) Users must be able to change passwords without asking me to do it. i.e. we assign dummy passwords when setting up there accounts. The password change utility within our webmail system is broken - requiring httpd to have root access to the /etc/shadow file. (now THAT is a security hole!) – Ryan Griggs Dec 19 '12 at 3:57
  • 2) chpasswd does not require the user to verify his existing password before changing the password. This is a necessity to prevent unauthorized password changes. Ditto for passwd. Also, regarding passwd, it requires SUID ROOT in order to allow a username to be specified. Tried SUDO but as per my first post, PHP doesn't handle this well. – Ryan Griggs Dec 19 '12 at 4:00
  • 3) Why did I write my own parser code? Short answer: I didn't! I copied it directly from the passwd.c file. Long answer: the getpwent/setpwent functions do not allow you to modify a password within the etc/shadow file. This requires direct manipulation of /etc/shadow as is done in passwd.c. So I'm doing exactly the same thing the passwd utility does when you change a password. How is this bad? – Ryan Griggs Dec 19 '12 at 4:02
  • passwd does ask for the users current passwd unless you're running it as root. Certainly chpasswd doesn't, but adding an autheitcation layer is straightforward. – symcbean Dec 19 '12 at 10:50

Not the answer you're looking for? Browse other questions tagged or ask your own question.