Storing passwords in mysql... use a hash right? but how do you send the user a forgotten password? - mysql

I've been looking into storing user passwords in mysql and the ubiquitous reply is to store it using an encryption algorithm like MD5 or SHA1. But what if user x forgets her password and wants it to be sent to her? What then? I can't send her the md5 hash! How is this issue dealt with in the real world. Are there two databases? One to compare hashes and another for forgotten passwords? But what's the difference, both would be read-only by the sql user connecting to it at that time. So how do you do it? Thanks!!

It's pretty standard security practice to never send users their password. Instead, you offer a password reset utility that is tied to their ability to access their e-mail account, and/or ability to answer question about their profile (like a security question or what postal code they live in).
Functionality Outline:
User clicks "forgot password link"
User enters security challenge information (e-mail address, security question if desired)
System sends password reset e-mail with auto-generated link (with generated GUID in a querystring for instance)
System creates a password reset record containing the reset GUID, what user it is for, and when the key will time out.
User retrieves e-mail, clicks on link.
System matches GUID, deletes password reset record, sends user to password reset page.

The best solution is to send the user a link where they can enter a new password without having to enter the forgotten one.
This link should only work once and it should work only for a few hours.
Don't create a new password and send that by mail; users will feel tempted to use that password (ignoring the fact that is has been transmitted over an insecure channel).

You are correct that passwords should not be stored in plain text (they should be hashed) and therefore cannot be delivered to users who have forgotten their password.
Essentially, what you desire is a way to circumvent your normal authentication scheme and you should first be aware that such a mechanism is a back door to the application.
Very often an assumption is made that only the desired user can access emails sent to the email address registered with your application. It is on this assumption that the 'standard' password reset mechanism is based. Here's my take on that:
The forgotten password page is requested and the user is asked to enter their registered email address into a form which they then submit
The receiving code checks that the submitted email address is indeed registered and if it is:
delete any existing password reset tokens for this address from the appropriate storage
generate and store a new password reset token for this address
send an email to the user which informs them that
'someone' has requested a password reset
to click the link if they do indeed wish to reset
to ignore the email if they did not request a reset
respond to the form submission with a page which says something along the lines of "if the address submitted was registered then a reset email has been sent"
If the submitted address was not one registered with the application then do nothing but respond to the submission with a page which says something along the lines of "if the address submitted was registered then a reset email has been sent" - just the same as if the address was a valid one (this is to make it more difficult for someone to discover email addresses registered with the application)
The user then receives the forgotten password email and clicks the link within it. The link delivers the password reset token to the application.
Upon receipt of a password reset token, the code checks that the token exists in storage and that it has not yet expired. If these hold true, then you assume that it must be the registered user who submitted the token and you can allow them to set a new password (a simple form with password and password confirmation inputs and a submit button and which contains zero personal information - not even their name).
Once the password has been set, you can direct the user to the login page where they enter their credentials as normal.
This isn't a perfect scheme. It's a trade-off between security and convenience and make no mistake that it constitutes a back door to the application. For low value applications it is usually good enough.
Further reading:
https://www.owasp.org/index.php/Forgot_Password_Cheat_Sheet
Forgot Password: what is the best method of implementing a forgot password function?
Why is "Forgotten Password" bad?

Related

How to change existing login form to ignore password manager?

We have an existing web site and we are changing the type of information that's required to log in. We are finding that users' password managers are still submitting the old information, causing the users' new login credentials to be rejected. The password manager is even passing fields that we no longer have in the page to our authentication code.
We have removed an input field, changed the form name and changed the names of the remaining input fields. We have had the users clear the browser cache, to no avail. When the users manually delete the information in the password manager, they can log in.
What else do we need to do so that the password manager does not fill in the old data for other users?

what does web-login actually means and how it is implemented?

Bear with me please. I am a layman in web technology and have few simple questions which need simple language answers.
When we login using a username and password on any website, what exact connection/relation is established with the website server? Is it that the server stores the IP address of the user and allows the user access to certain tables from the server database for a short span of time and the regular query to the server keeps the 'connection alive'?
Thanks in advance..
A login system receives a set of credentials from the user, typically an identifier and a password. It could include what is called an authentication token, which is either generated by a handheld device (so you not only have to have id and password but the token generator; it's on the equivalent of requiring both the pin and the card at an ATM), or it's generated by combining the password with something else and returning an encryption result.
The login system, once it receives the credentials, compares them to what is stored on the credential database. In some cases the credentials are sent encrypted, such that even the login system doesn't even know what they are, all it does is determine if the encryption is correct. This would mean that even if someone was monitoring the communication channel they could not use it to fake a login later.
Now, if the credential is valid, one of two things happens. For a desktop application or general sign-on, the login program will transfer control to either the rest of the program (for an application), or grants access to the system (for a sign on). When the person leaves the application or signs off the system, then everything starts over.
For a website, the login program will send the user a cookie that another part of the website can read and determine the user was authenticated and their credentials passed. This continues until the cookie expires, or the user logs out. If the user logs out, the website sends a new cookie that says the former cookie is expired.

How to update DB records using a dynamically generated link

I have a requirement to generate an email to administrator whenever a user sign up. Administrator will approve the registration by clicking on a link provided in email and database should get updated, without admin to login to administrator console.
I am looking for best practice to code this scenario with keeping application security intact. I can generate email with dynamic rendom value attached to the link(provided in email) URL, but i am not sure how to keep a track of this on application side?
Any thoughts?
You could generate a random validation number when the user signs up, and store it in the database with the user record. Then generate an email with a link such as
http://foo.bar.com/approveUser.action?userId=<theUserId>&validationToken=<theRandomNumber>
When the approveUser action is invoked, check if the validation token stored in the database for the given user ID matches with the token sent as parameter, and if so, approve the user.

Hide the a saved password from the source

I have a login form and an option to remember the password. The password is encrypted in a cookie on the users computer. At the moment it is decrypted and placed in the password field. This isn't that flash as you merely view the source to see the users password.
Whats the best way to secure the password from the source?
Don't do that. ANY secure implementation of a login form will not make the password readble EVER.
You have two options:
Use the cookie to log-in the user automatically. Very convenient, that's what most people want to have.
Let the user save his password in the text field. Every browser can do that in a more or less secure way and skip the cookie.
Let me say it again: Displaying the clear text password in the code is a security risk. However, you knowing the user's password or being able to recreate it (symmetric encryption instead of hashing - what you should use) is a complicated thing, since I mistrust every website which knows my password in clear or stores it anywhere unhashed.
So, you'd go with taking the password from the user at registration time, hash it and store it in the database or whereever you like. Then, take the cookie to remember the user (means the identity, not the credentials to verify that identity).
Don't have an option to remember the password. Browsers can do that on their own, securely. Instead, use an option to keep the user logged in. In that case, you set a cookie to maintain the user's session between server sessions that's based on a session token (usually including an encrypted username), not a password.
You should never be able to decrypt a user's password to readable plain text. Use hashing instead of encryption. Instead of sending plain text to the server, you can hash the password on the client-side with an algorithm like SHA1. A lot of apps skip this first step, but it's preferable never to even transmit the password in clear text. Then, on the server side, hash the "password hash" again with an algorithm like HMAC-SHA1, using dynamic salt as a key. You should use different, random salt for each user's password. That way, even if two users have the same password, the salt ensures each password is saved differently. You store the password and the salt in your database for each user, so it can be used again when comparing to the user's password on each login.
Whether you store a session token that includes a username, or a user's password (which should only be a hash of the password, and is still inadvisable) in the cookie, you should encrypt the cookie (as you state you already have) and decrypt the cookie on the server side, not the client side. If you decrypt client side, then you've given away the algorithm and key to do so, which would make the encryption a pointless exercise. Additionally, if you decrypt server side and then send the password back down the pipe to preload your login form, you expose the user's password during transmission to the browser, and do so again when they resubmit the login form from the browser.
When the user makes the first request after returning to your site, you will get the cookie in the HTTP header, so if you use a session token instead of a password, you can immediately decrypt the cookie, verify the session token is still valid, log the user in, and take the user to a content page. This is what every site that allows a persistent session cookie does.
If you store the password in a cookie, I assume you're also storing the username, or sending the username from the server to the browser. When you then preload the username and password in your login form in clear text, you give a thief credentials to use on your site and potentially others. You leak information about the user. If you store a session token in the cookie (which contains a username and an expiration timestamp instead of a password), and only decrypt the token on the server, then you haven't leaked any user information. Additionally, you can use an HttpOnly cookie as your client script doesn't need to read the cookie.
From your perspective, both methods accomplish essentially the same thing for your users, but an encrypted session token that includes only the username poses far fewer risks for the user than a password that is stored (encrypted or not) and/or decrypted to preload your login form.
To create a session token, create a cookie and add the username and your choice of an issue date and/or an expiration date. If you set the issue date, then you can always calculate the expiration date based on your current expiration policy on the server. If your policy changes, then it always applies to old tokens as well. If you only set the expiration date and verify the current date is less than the expiration date, then you are using whatever expiration duration policy you thought up at the time you stored the cookie. Session tokens often include the following:
Username - so it's specific to a user account you can verify
Issue Date - the current timestamp
Expiration Date - current timestamp + expiration window
Persistent - A property indicating whether the cookie should stay persistent or expire at the end of the current server session
Any custom data (sans any passwords)

Is it necessary to double-check a user's password on registration?

Edit - migrated to ui Stack Exchange (please close this question)
Do you find it necessary/worthwhile to make a user repeat his password in a registration form, assuming that form includes an email address?
Pros: I imagine there are quite a few cases where users mistype their password in the registration form.
Cons: If you require a valid email anyway, he can always retrieve/reset his password via email - and for the users that do get the password right in the first try, this is yet-another-field-in-the-registration-form (which I prefer be as simple as possible)
I would say using the password reset functionality in place of double-entry is not horrible, but it would require a decent UI on the login page to ensure the "forgot your password" link is clear -- such as having it appear much bigger upon invalid password entry.
I'd personally go a different way: ask for the password after a 'verify your email address' message.
One thing to consider is you also need a valid email address -- so if they mis-enter their email, and also their password, their account is effectively locked. Many sites require clicking a link (and/or entering a code) upon account creation, in order to verify email address, before making the account active. If you're doing this, then there is an annoying UX thing to avoid: it's not always clear why my account doesn't work.
I've seen this personally where I enter a password during registration, but then it tells me "invalid password" when I try to login, rather than "your account is not yet activated". Minor, but an annoyance.
One way to get around this is to not ask for a password until they've clicked the link in the email, then you prompt to create a new password. You can use double-entry here, since it's the only thing on the form, and it's a pretty simple way to avoid an easy user mis-entry. Users are also quite used to this model, practically every password entry system works like this.
It also handles an additional use case, where the user themselves is not the one creating the account (not sure if this applies to you or not). Someone can create the account on the user's behalf, but then the user is still choosing their own password after clicking on the 'verify' link they get via email.
I do think that it is worthwhile - as an additional validation just to ensure that users havent mistyped the password (especially coz we cannot see the password being typed in most cases). I think it provides a sense of validation to the user as well that he is in fact sure of his password before he submits the form.
However, this is valid only in case of forms which do not allow you to copy / paste from one field to the other (I have used sites where their forms allow me to copy paste which inherently makes having the 2nd field completely useless)
Personally, however, i find it extremely irritating when a form makes me re-type my password. But i still do think that its a useful validation to have.