Passwords MD5 encoded without salt. How to fix it? - security

I have a system where users can signup by Facebook or by a regular form. If user signup by Facebook, my system generates a random password, just to allow user to log-in without Facebook if he wants. If user signup using regular form, he can type any password he wants. In both ways, password are encoded into a MD5 hash, but without salting. It's is insecure, I know, this is the reason i'm here.
I don't know the best strategy to convert the passwords into secure ones... First i'm thinking to keep the MD5 insecure password, and when user log-in, i can match the password without salt, salt-it, and then update the database. But it doesn't solve my problem, because system will still accept the insecure password. Besides that, user can still log-in using facebook, witch do not allow me to update their password (since he didn't used it).
So, have anybody an idea to minimize the impact instead of just force everyone to update the passwords?
Thanks!

So, I've done the following actions to solve my problem.
Created a column "LastPasswordChange" in users table.
When user changes password, the field is updated with current date, ALSO, an e-mail is sent to user to inform that password was changed, with a link to revert it in case of this is wrong (due to a possible hack).
The e-mail allow user to log in and set a new password without knowing the last used.
When user log-in using the current password, it looks to the LastPasswordChange field, and if it is null, it allow the login without using the salt.
In any way he/she logs in (Facebook or Login/pass), system looks to the LastPasswordChange field, and if it is null, system requires user to change the current password to a different one (not match the old one without salt).
That's it.

Related

Temporary Password Security - Storing as Plain Text

How much of a security issue would it be to store temporary / machine generated passwords as clear text in a database?
I understand that passwords should be encrypted using a 1-way hash function with salt. This is especially true for user supplied passwords as users typically re-use them over and over again. If the database was stolen, a thief might be able to gain access to user user accounts on 3rd party websites such as: utility bills, social networks, even potential for online banking.
How much of an issue would it be to store temporary/machine generated "welcome" or "reset" passwords as clear text in a database? The password would be emailed to users and must be changed upon login. The passwords that they supply would then be hashed.
The reason for me asking is that there are a some nice properties to storing a temporary password as clear text. For example, if a user does not get the "welcome" or "reset" email, an admin can quickly look-up their temporary password.
Because the temporary password would be machine generated, if the database was stolen, the thief would not be able to access any 3rd party websites that the users log into. The thief would however be able to login to the application that generated the temporary passwords.
Assigning these passwords a small "expiration" would limit exposure, but overall I am just looking to see how dangerous this approach would be.
You should not store even machine generated passwords in plain text.
Let's see what an attacker can do, if he somehow gains only read access to your database with SQL-injection (i made a small demo how easy SQL-injection can be, just click the next-arrow to get a malicious input).
The attacker with read access, could demand a password reset for any e-mail address he likes. Because he can see the new generated token in the database, he could call the reset page with this token and therefore can change the password of this user. Unnecessary to say, that he can now impersonate the original user.
Handle the token just like every other password, even if it can not be used on other sites. The data accessible by the user-account could contain other data (like birthday, real name), that can be used to hack other sites.
You absolutely must not store passwords in a database at all, let alone in plain text. You should store hashes of them. See this answer for why. Then you need to build all your password-reset facilities around that fact. See also this answer about password reset features.

Time limited, or one time use, password reset tokens?

Users forget passwords, and (nearly) all membership sites need a way to help users get back in.
I'd like to implement the common scenario:
User hits site, tries to log in, can't, and realizes they forgot password - crap!
User enters email address and clicks "forgot password"
User gets email with a password reset link
Here's how I'm planning to implement this (C#/ASP.NET MVC):
When the user enters email and hits "forgot password" button my site will generate a GUID, store it on the member's entity in the DB (member.ResetToken), and email them a link with that GUID in the url (the email sent will inform them they can use this link to one time only)
User clicks the link and my site looks up their account based on that member.ResetToken from the url. If their account is found show them a password reset form, and when they complete the reset it clears the member.ResetToken from their account.
Here's my question: keep it like this (in which they can reset their password with that link at any time, now or in the future) or add a timestamp to limit how long they have to reset their password?
From a UX perspective the ability to reset your password whenever you're ready is great, but I want to make sure I'm not overlooking some security issues this could raise.
Your scheme actually works, but there are some points that could be improved. But first to your original question about the time limit:
Let's ask the opposite question: Why should a token remain valid infinit?
There is no advantage, when the reset-link can be clicked two years later, either the user clicks the link in about an hour or he has probably forgotten about the link (and can request a new one if necessary). On the other hand, being able to read the e-mails doesn't necessarily mean, that an attacker must hack the e-mail account, there is for example the open e-mail client in the office, a lost mobile phone, a backup on the (lost) USB drive...
The most important improvement is, that you should only store a hash of the token in your database. Somebody with access to the database (SQL-injection), could otherwise demand a password reset for any e-mail address he likes, and because he can see the new token, he could use it to set his own password.
Then i would store those reset informations in a separate table. There you can store the userid, the hashed token, an expiry date and the information whether the link was already used. The user is not in a special state then.
Maybe i misunderstood this point, but the reset link should point to a special page for password resets. When the user goes to the login page, there should be no special handling, the login page should not be aware that there is a pending password-reset.
The reset token should be unpredictable, this can be achieved best with a really random code, reading from the random source of the operating system.
So, there are a few problems with this approach that I was trying to elude to in my comment. When you store the "confirmation token" in the users password, you have just basically destroyed their password.
I, a malicious person, can then take a big giant list of email addresses and a bot net and flood your server with password reset requests and lock out your users from their account. Sure, your users will get an email for the reset, but if I can reset passwords fast enough, there may be a backlog of emails (or, if you do it synchronously, i can likely DoS the entire application).
I, a normal user of your system, may attempt to reset my password, and can't figure out why I'm not getting the reset email because I don't even know about a spam folder (or it never arrived). Fortunately, I just remembered what the password was, but it doesn't work anymore since the password is now an opaque GUID, and I'm basically dead in the water until I can find the reset email.
Here's the process you should use.
Generate a password reset request which you look up using a GUID, and you could likely also secure this by hashing that value with some private data and passing that in the URL as well to avoid a rapid attack. You can also lock this request down by making it only valid for a certain amount of time.
Once someone follows that link with a valid token and any other parameters you specify, they can then change the password, at which point you can now safely change the users password.
Flag the password request as having been completed, or delete it. You could also track information like IP address or something similar if you are really concerned about who changed the password if you are really concerned about it.
Send the user an email confirming that they have changed their password.
Also, just in case this isn't happening already, make sure you are hashing and salting the users password. It doesn't sound like you were doing that when you were just replacing the password with a GUID, so just double checking.
Users also forget to reset passwords (things happen). Being paranoid about passwords, I'd suggest limiting the link lifetime to 24 hours. This should be more than enough. It doesn't solve the problem of malicious intercept but it is better than nothing.
I would make the following suggestions:
Require some piece of information before the user is allowed to click the forgot password button. For example, require an email address and date of birth.
Ideally your user interface should not provide any feedback that allows a hacker to determine if his reset request succeeded. You don't want them farming your page for email addresses or DOBs. However this is a usability tradeoff, so whether you do this depends on how much security you really need.
You might also considering requiring a captcha which makes brute force and application DoS attacks much more difficult.
Expire the one-time token as quickly as possible. A couple hours is enough in my opinion. You should never consider email to be private-- it isn't, unless you are using a secure email technology (e.g. PGP) on top of the base protocol (most people do not). The last thing you want is for a black market to open up where your GUIDs are bought and sold, which is exactly what could happen if they have infinite lifespan.
Do not use GUIDs. They are not cryptographically random and are guessable. I suggest you use a cryptographic random number generator and translate it into base64.

Is it really dangerous to save hashed password in cookies?

There are many discussions about security risk for saving hash password in cookies, as upon accessing to the user's computer, a hacker can log in with the saved password. If a hacker has access to the user's computer, he can catch the password, as browsers also save passwords locally (encrypted of course). What is the difference between password set in cookies with that saved by the browser?
For obvious reason, a temporary GUID should be send instead of password. In any case, I believe that limiting access to the logged IP can close doors for attackers to use locally saved GUID. Of course, it will limit the length of logged period, as IP is usually dynamic and regularly changes; but I think it is worth of its noticeable security. Any idea?
I suppose the reason why you would want to store a hashed password in a cookie is to create a "remember me" cookie. So you need a value for the cookie that is secret, so that not someone else could easily guess it. Anyone with access to this value would be able to log in as this user, so it is actually an "extra password".
There are two risks involved here:
Most important is the risk of exposing the password. This would not only put your site at risk, but potentially other sites as well. Most users re-use their password for everything, and the password would probably give an intruder access to both the users email account and netbank. Someone with access to the hashed value may use brute force or rainbow tables to discover the original password (rainbow tables are long lists of pre-calculated hashes). Rainbow tables are easily available for passwords up to more than 8 characters, and even longer. You may avoid this by salting the password so that it is i.e. more than 20 characters before you create the hash (remember to store the salt in the cookie as well). A properly salted password hash calculated with a safe hashing algorithm should be quite safe.
The other risk is connected to the fact that the user must change his original password to make the hashed password string invalid. It is impossible for the user to actually turn off this feature once it is turned on. You may delete the cookie when he un-checks the "remember me" button, but that will have no effect if the cookie already is compromised. What if his computer is i.e. stolen? If the user has checked this button on one computer then he must have access to that computer to disable this feature.
Yes, it's less secure to use the hashed password in a cookie. There is a difference between saving it in the browser and sending it over the wire: unless you're always using SSL, an attacker doesn't need access to the machine to read the cookie out of the request.
It's much safer to send a random value, as then there's no tie to the user's actual password: it's possible to expire a session by forgetting the random value, without having to get the user to change their password. Also if the attacker does get the hashed value out of the cookie, it may be possible for them to recover the actual password if that's what's sent.
as upon accessing to the user's computer, a hacker can log in with the
saved password. If a hacker has access to the user's computer, he can
catch the password, as browsers also save passwords locally (encrypted
of course).
Not sure what you mean here. If you ask IE to remember your password for a site and someone has the password to your computer and can use your IE then yes, he can log-in using your password. But this is not related to hashing or cookies etc.
First of all, a hashed password can not be retrieved. So if someone has the hash of your password, he does not know your password.
When you login to a site that requests a password, you provide the password which is send encrypted. The standard practice is to store the user's password as a hash i.e. not the password itself. So you type the password and the receiving server will compare the hash with the one stored.
Now related to your question on sending the hashed password inside a cookie, this is related to session management. I.e. to determine whether a user has already succesully loggedin or not.
IMHO using just the hashed-password as a way to determine if the user has already logged-in when using plain HTTP is not a good idea.
But if this what you ask, it is another topic.
I.e. how to best do session management over HTTP connections
Times when you should ask the user to re-enter their password:
When they try to change their password.
When they try to change their email address.
When they try to change their security information (anything that can be used to recover their password, including username, email address, security question, etc.).
When they try to access highly secure account information and have not entered their password for more than 15 minutes or so (if all information is highly secure, you should flat out log them out for inactivity instead). Amazon does this a lot.
Saving a hashed password makes this less effective.
As an aside, you should already be using cookies that are Secure (won't transmit over HTTP), HttpOnly (not accessible via javascript) to protect against XSS attacks. Of course, if someone hacks the person's machine completely they'll just install a keylogger.

Is there anything we can do to prevent multiple users being assigned the same password?

I have a web application that handles employees work sheets.
They have username/password combinations assigned to them from an admin.
The passwords are salted and hashed individually.
The problem is, they are all being assigned the same password by the admin. This is obviously a security problem.
I don't want to error with the password you are trying to use is already in use because...
It reveals someone else has that password. Bad security.
I can't easily compare passwords. I need to salt and hash them individually because of the way they are stored in the database.
Do I have any options to try and limit this behaviour?
The software should force users to change their passwords after logging in for the first time. Have the software check to make sure the user actually enters a new password, rather than repeating the old one.
This isn't a technical problem; it's an organisational/management issue...
The admin simply needs to stop assigning the same password to everyone.
Why is everybody being assigned the same password? Give them a temporary password of a random string or allow them to pick a password of their choosing when registering.

What is safer? Should I send an email with a URL that expires to users to reset their password or should I email a newly generated password?

I was wondering what would be the safer option when users have forgotten their password
Send a randomly generated new password to the email address (all email addresses in my database are confirmed to work).
Or
Send an email with a link that expires within a certain time frame where the user can reset their password.
Aside from the fact the latter uses an extra table, what do you think is safer/better practice?
If you send an email containing the password, it means :
The password will go through some networks (unencrypted) and could be "seen"
The password will stay in the user's mail box
Which can be hacked
And just any one who has access to the computer might take a look
So, sending the password in an email doesn't seem that safe...
As a user, I would feel my password is "safer" with the link that contains some kind of token and expires after a while.
That "expires after a while" part is important, btw : it makes sure that if someone clicks on the link after some time (for instance, someone who accesses the user's mailbox), the link will not be used to generate a new password.
Of course, this means I won't be able to just "search in my mail box" to find the password -- but I can always ask for a new one I have forgotten it again ^^
Rather baffled by the other answers here. They're exactly the same. Both give access to the user's account, both are sent in plain text, and both are in common use. Pick whichever you prefer.
Enforce an immediate password change once they use the link/password, and have the link/password expire after 24-72 hours.
Send an email with a link that expires within a certain time frame where the user can reset their password.
That one, definitely.
E-mail is always in the clear (potentially your site connection may not be), and can touch more machines. Keep passwords out of e-mail. The temporary reset token also means that if the mailbox is hacked later on, the token is of no use any more.
Aside from the fact the latter uses an extra table,
It doesn't have to. You can generate a cryptographic token authorising a particular user to reset a password within a certain time frame; no extra data required.
An example using a HMAC based message authentication code (fancy hashing):
details= user_id+' '+token_expiry_timestamp
mac= hmac_sha2(server_secret, details)
token= details+' '+mac
then send the token to the user as part of the clickable URL in a mail. When you receive a click back, work out what the mac should be for that user and time with your server-side secret, and check that against the passed-in mac. If it matches, it must be a password request you signed earlier.
user_id, token_expiry_timestamp, mac= token split on ' '
details= user_id+' '+token_expiry_timestamp
if hmac_sha2(server_secret, details)!=mac
complain
else if token_expiry_timestamp<now
complain
else
allow password for user_id to be changed
This requires no state, but you should use shorter expire times as the tokens could be used multiple times if you do not record usage.
One difference that people seem to have neglected is that - taking a web application for example - a password reset option is usually open to anyone who accesses a site and knows the username/login of the account that they want to reset the password for.
By sending a link in an email that the user has to click in order to be able to reset their password, you avoid letting users accidentally or maliciously reset other people's passwords - all that will happen is they receive an email that ends with, "If you did not ask to reset your password, please ignore this email."
Even if it's not a security risk per se, resetting passwords without confirmation could be a major annoyance.
Obviously the latter is much safer. Email is like a postcard. Pretty much anyone can read it who wants to. Also, once the password is changed, send an email to close the loop.
As long as the URL doesn't ask for a password or some such, it still is better than the randomly sent password but only because it doesn't leave the password in plain text in an Inbox.
In other words, the link reduces the window of opportunity.
I've always been a fan of setting a hashcode and giving them a link.
Sending an email to the user afterwards letting them know they requested a password recovery link, and after they set one telling them their password was changed is usually a good courtesy in case there was a violation.
A user will very quickly react to an email saying their password was changed if they didn't mean to do it.
Unfortunately there is no real "SAFE" way. Security Questions an pins can help but are never truly secure.
Send them an email with a random, one time use,
password.
Force them to change the
password when they first arrive.
Notify them that they changed their
password.
Sending the random password is as much of a risk as sending the link. i.e. anyone can get the email first and log in as the user the first time.
By forcing the change, whoever gets their first can not get there again without setting a password.
Notifying the user of the change tells them that the password has been changed, and this can happen before the attacker can actually log in and change the notification email.
So, if someone were to get to the site first, the original email to the user will no longer work, as the original password is no longer valid. Also, they'll be notified of the password change.
This provides an opportunity for them to notify sys admins when they show up and find they can not log in to their account.
None of these stop the ability of a person intercepting the email and getting SOME access, but at least it lets the original, vested, user know something is amiss.
Some have stated that both are equivalent - this is not true for following reasons:
1) With reset link if attacker has access to email and consequently uses reset link to change password, they will alert user even if the actual reset email and notifications are deleted by attacker. With mailing password if user requests reset and attacker sees the random password (even much later), then attacker can access user's account on your site without alerting user.
2) Also if you mail a password the user may be tempted to re-use the password on other sites and attacker with access to email has access to other sites even if the other sites were not vulnerable to account take over via account recovery.
With both random password sent in email and reset link, if attacker controls user's email, they have access to user's account. What you can do in this case, depends on how many handles on the user you have - for example, if you have their primary and alternate email address, then you should send notifications to both email accounts when reset is requested and used or if they have a phone, you could send them a text in addition to email, etc. You can monitor usage itself but that is harder.
A couple of other issues:
Can the link be used multiple times? Apart from expiring and having unpredictable value (with attached MAC so it can be verified without server state), you may want to have an internal alert go off if an attempt is made to reset password on an account multiple times (register success/failure, remote ip address, timestamp, etc) and abort after first and put the account in some inactive state.
It would be a good idea to see how much abuse is happening to see if you need more defense mechanisms to prevent account takeovers via your account recovery flows (depends on the value of an account).
Also very important in this case to keep up-to-date on email addresses and other contact information if you can (email addresses do get recycled when not used) and how email address or other such information can be updated/added and notifications.
As always make sure your notifications (text, link, landing page) don't make it easy for phishers.
Some of these issues of course may not be very relevant unless you have a large site.
Send them a link so they can later reset their password. This forces them to confirm somewhat its actually their account they're resetting the password for. If you reset the password without sending an email, anyone can log in to the site and reset anyone else's password. This creates a denial of service type vulnerability.
Although I may be repeating some answers, I feel compelled to respond because we recently had some issues with faulty password recovery tools. One of my coworker's personal accounts was compromised which allowed our google hosted domain apps to be compromised. Due to undeleted plaintext passwords and stupid password recovery questions that were googleable other accounts were compromised as well.
Suffice it to say, I am a strong adherent to emailed links that expire after 4 hours. I sat there for 4 hours logging into one of our accounts after receiving the link making sure it was still uncompromised. 24-48 hours would be waaaay too long to have to do that. 4 hours was too long. A randomly generated password that the user is required to change upon next login is second best, but it is completely dependent on the user actually logging in. The password is changed permanently, whereas if the user does nothing with the link, the password will not be reset.
There is no perfect solution against a dedicated individual who wants to compromise your system. There are better solutions than others.
Extending from bobince's solution... Here user is required to reenter userId and token on password reset page.
On request for reset password page
urserId = Input userId
token = Randomly generated token (or one time password)
tokenExpire = Decide token expiry date/time
Store in DB tokenExpiry for this urserId
urlToken= MD5 hash value of (urserId + token + tokenExpire)
pwdRestURL = server pwd reset url + "?urlToken=" + urlToken
Send above generated URL and make sure you do not
include either of userId or token in email
Display token to user (This is to be used on password reset page)
.
On password reset page (using above pwdRestURL URL)
urlToken = Token from URL request
userId = Input userId
token = Input token
tokenExpiry = tokenExpiry from DB for this user
resetToken = MD5 hash value of (urserId + token + tokenExpire)
IF
resetToken == urlToken
AND tokenExpiry for user is valid
THEN
Clear tokenExpiry
Allow user to change password
ELSE
Display Error
END IF
.
Advantages of above approach:
Even if email is some how exposed in
network, no one can reset password
without knowing the userId and token.
Token has an expiry period
No clear test personal information is
relayed over email
i agree with will's process.
however if you only choose between the options you have given, although both options are essentially the same in that you're sending information via email, i think the latter is a more common method.
if a hacker was to request a new password, the user's old password would no longer work. at least with the latter option it doesn't actually change any user details.
Everybody except for ceeyajoz is using flawed logic. Its hard to think about security.
Both cases use of email which is in plain text. Both are equally insecure when email gets hacked.
It doesn't matter if the URL expires since the email is hacked the hacker can just request for another password reset URL. If the temporary password has changed, the hacker could just request a new one. Either way you are screwed.
So I say just send the password, this way its one less step for the user to pick a new one.
EDIT
When I said "send the password" it was in the context of the OP where you send a new random password.

Resources