Jump to content

Recommended Posts

So I spent most of last week learning about the proper way to Salt, Pepper (or Vinegar) and Hash User Passwords.

 

And I think my "create-account.php", "log_in.php" and "change_password.php" scripts are pretty secure.

 

Now I could use some help on handling my "password_reset.php" script.

 

Is it okay to use MD5 to generate a Temporary Password and e-mail it to the User, or does that defeat the purpose of Hashing, Salting, etc.?!

 

 

Debbie

 

Link to comment
https://forums.phpfreaks.com/topic/256585-password-security-during-password-reset/
Share on other sites

Why not just email them a link to a page where they can reset their password instead? The page can expire after X amount of time.

 

I am doing that in essence, except I make them paste in the temporary password.

 

Regardless, my question centers around what to do with Hashing and Salts and Pepper for the Temporary Password Re-set?!

 

Should I just generate a Temporary Password like this...

$tempPass = substr(md5(uniqid(rand(), true)), 3, 10);

 

...and then retrieve the User's CURRENT SALT and use that to create....

$newHash = hash_hmac('sha512', $newPass . $existingSalt, VINEGAR);

 

(Or should I generate a new Temporary Salt as well?)

 

And to your earlier comment, isn't it better to re-set the Password and make them Log-In and then make them choose a New Password?

 

 

Debbie

 

 

You could do either way, but I think it's a better idea to not remove or alter their original password and just have them reset it themselves with a new password. That way you won't have to generate any temporary passwords or salts or even worry about how safe the temporary password is because there is none.

Add two additional columns in your users table, something like "reset_pass_code" and "reset_pass_date". Make "reset_pass_date" a DATETIME (or you can use UNIX timestamps if you prefer).

 

The general idea is that when a password reset is requested, you generate a string, store it in the database and send it to their email. You also fill the reset_pass_date with the current date.

 

Then when they visit say, reset_password.php?userid=1&code=blurgablurg, then you can lookup that userid and code to make sure it matches. You can also make sure the reset was requested within the last X amount of time, like 24 hours or something.

 

You shouldn't change their actual password until they visit the reset page and do it themselves. The reason is because anyone could say the password is lost, and if you change it then it would no longer work. With the method above, if someone else filed a reset password request it would simply email them and they can ignore it if they want.

 

As far as the actual code goes, really any method of randomly generating a string will work fine. But in this case longer may be better, so if you use MD5 make it the full 32 characters.

You shouldn't change their actual password until they visit the reset page and do it themselves. The reason is because anyone could say the password is lost,

 

Interesting

Now I have it where a user goes to forgot-password.php, enters their email and a new md5 password is sent to them.

 

I was thinking if someone was enterested in a product, contacted the owner, didn't like the converstation, got mad and then just for kicks went to forgot-password.php and entered the owner of a products email(which they would get from emails back and forth about the product or service) and then resets the owners password. (That would be a b....)

Another reason for not actually changing a user's password is that they then may not remember to update their password once they log in -- if you force them to via a temporary password/specific link then you don't have this issue. This is both nicer from a user's perspective and more secure; the time frame in which the password/url that was sent in plain text works is definitely limited.

 

Why not just email them a link to a page where they can reset their password instead? The page can expire after X amount of time.

I am doing that in essence, except I make them paste in the temporary password.

 

Why? I don't believe this adds any security but it is definitely more frustrating from a users point of view.

 

 

 

 

Another reason for not actually changing a user's password is that they then may not remember to update their password once they log in -- if you force them to via a temporary password/specific link then you don't have this issue. This is both nicer from a user's perspective and more secure; the time frame in which the password/url that was sent in plain text works is definitely limited.

 

Why not just email them a link to a page where they can reset their password instead? The page can expire after X amount of time.

I am doing that in essence, except I make them paste in the temporary password.

 

Why? I don't believe this adds any security but it is definitely more frustrating from a users point of view.

 

It adds no security at all. Someone can brute force POST just as easily as GET.

scootstah,

 

I was almost done with my User Account module and you guys are making the last piece tough?!    :P

 

Before we go down the path you are suggesting, I'd appreciate a sense check of what I currently have..

- User clicks (Forgot Password?) link
- User is taken to "Reset Password" form and asked for E-mail
- User enters E-mail and clicks "Reset Password"
- System looks up E-mail in database
- System generates a Temporary Password
- System generates a Temporary Salt
- System generates a Temporary Hash
- System finds User based on E-mail entered
- System updates Member table with new Hash (i.e. Password)
- System sends e-mail with new Temporary Password and a link to Log In
- User copies Temporary Password
- User clicks on Log In link
- User enters E-mail and pastes in Temporary Password
- System logs in User
- System redirects User to "Change Password" form
- User enters E-mail, Temporary Password, New Password, Confirms New Password
- System changes Password
- System redirects User to index.php

 

What do you think?

 

And if it needs to be improved, where would you make changes?

 

 

Debbie

 

 

- System updates Member table with new Hash (i.e. Password)

 

After that, does the original password still work?  What happens if I go there and submit a reset request on behalf of some user then they just delete the email rather than follow the process.

 

- System updates Member table with new Hash (i.e. Password)

 

After that, does the original password still work?

 

Right now I just reset the forgotten password with a Temporary Password.

 

If I created a Temporary Password, store it to the side, then how does my script know whether a password is "real" or "temporary"?

 

 

What happens if I go there and submit a reset request on behalf of some user then they just delete the email rather than follow the process.

 

I dunno.  If that happened to me, I wuld eventually just try resetting my own password since I would be locked out.

 

What do you think I should do?

 

 

Debbie

 

P.S.  I appreciate the suggestions from the peanut gallery, but it also appears that my simple Password Reset can be made increasingly difficult if we really try...

 

 

one way of doing this is to create a fiag in the DB that differentiates if it is Temporary or there REAL password. ;)

 

Except scootstah in Reply #4 said to create additional fields which is making my code complicated to say the least...

 

Scootsah, how did you plan on my script know where to look for the valid Hash between two fields?!  :shrug:

 

 

Debbie

 

Scootsah, how did you plan on my script know where to look for the valid Hash between two fields?!  :shrug:

 

You login script would only look at the actual password hash field.  Scootsah's method (and what I do aswell) involves just creating some temporary code which is used only for the reset.    Process goes something like this:

 

[*]User requests a password reset by entering their email

[*]Find the user by email and generate a random value.  uniqid or a quick md5 of say the email+current time is good enough

[*]Save that value as well as the current datetime into that user's db record in new fields, ex: ResetCode, ResetRequestedOn

[*]Email the user a link such as http://www.example.com/resetpass.php?code=<the generated  code here>

[*]When the user visits that link, take the code and attempt to find a record with that code (SELECT ... WHERE ResetCode=:theCodeFromUrl)

[*]If found, and the the difference between ResetRequestedOn and now is less than, say 24 hours, show them a form where they enter their new password

[*]Save their new password to the database, optionally with a new salt value, and NULL-out the ResetCode and ResetRequestedOn fields

 

Edit: kicken beat me to it, but I'd already typed this out so you may as well have it too (our approaches are essentially the same).

 

Personally, my approach would be as follows:

 

1.) Leave the users table alone

2.) Create a new table, lets say, password_resets, with 3 fields: user id, request_time, uniqueToken.

3.) When someone wishes to reset a password, ask for the email address.

4.) Send the user an email something like: "To reset your password, click this link (or copy/paste): http://example.com/resetpassword?token=307gjhse03a0924njf08u234hjg

5.) Ensure reset password checks that the token was created recently (say, within the last 30 minutes). If so, let the user pick a new password.

 

Note that until step 5 happens, their old password works ok (which is good, as it means someone can't lock you out and if you remember your password you can ignore the reset email). As noted above, this also removes the need for the user to copy/paste a temporary password which adds nothing to security. It also removes any issue with real vs temporary passwords and salting and shouldn't be too tricky to implement. Just make sure the unique token isn't guessable.

one way of doing this is to create a fiag in the DB that differentiates if it is Temporary or there REAL password. ;)

 

Except scootstah in Reply #4 said to create additional fields which is making my code complicated to say the least...

 

Scootsah, how did you plan on my script know where to look for the valid Hash between two fields?!  :shrug:

 

 

Debbie

 

 

It's really not complicated, and it is by far a better approach.

 

The "valid hash" doesn't change until the user changes it themselves. Don't just change the password as soon as someone hits forgot password. That would irritate me to no end if all of a sudden my password didn't work because someone locked me out.

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.