Best way to handle user account authentication and passwords - security

What is the best way to handle user account management in a system, without having your employees who have access to a database, to have access to the accounts.
Examples:
Storing username/password in the database. This is a bad idea because anyone that has access to a database can see the username and password. And hence use it.
Storing username/password hash. This is a better method, but the account can be accessed by replacing the password hash in the database with the hash of another account that you know the auth info for. Then after access is granted reverting it back in the database.
How does windows/*nix handle this?

This is a better method, but the account can be accessed by replacing the password hash in the database with the hash of another account that you know the auth info for.
There's really no way around this. Anyone who as write access to the password file has complete control of the computer.

This was a common issue in UNIX many years ago, and was resolved by separating the user identity components (username, UID, shell, full name, etc.) from the authentication components (password hash, password hash salt). The identity components can be globally readable (and in fact must be, if UIDs are to be mapped to usernames), but the authentication components must be kept inaccessible to users. To authenticate a user, have a trusted system which will accept a username and password, and will return a simple result of "authenticated" or "not authenticated". This system should be the only application with access to the authentication database, and should wait for a random amount of time (perhaps between 0.1 and 3 seconds) before replying to help avoid timing attacks.

I'd go with 2 but use some salt. Some pseudocode:
SetPassword(user, password)
salt = RandomString()
hash = Hashfunction(salt+password)
StoreInDatabase(user, salt, hash)
CheckPassword(user, password)
(salt, hash) = GetFromDatabase(user)
if Hashfunction(salt+password) == hash
return "Success"
else
return "Login Failed"
It is important to use a well known hash function (such as MD5 or SHA-1), implemented in a library. Don't roll your own or try implementing it from a book its just not worth the risk of getting it wrong.
#Brian R. Bondy: The reason you use salt is to make dictionary attaks harder, the attacker can't hash a dictionary and try against all the passwords, instead she have to take the salt + the dictionary and hash it, which makes the storage requierments expode. If you have a dictionary of the 1000 most commaon passwords and hash them you need something like 16 kB but if you add two random letters you get 62*62*16 kB ≈ 62 Mb.
Else you could use some kind of One-time passwords I have heard good things about OTPW but havent used it.

Jeff Atwood has some good posts concerning hashing, if you decide to go that route:
Rainbow Hash Cracking
You're Probably Storing Passwords Incorrectly

You could use openID and save no confidential user passwords at all. Who said it is for websites only?

A very bad idea indeed. If the database is compromised, all accounts are compromised.
Good way to go. If your hash algorithm includes the username, replacing the password hash with another one will not work.
Unix stores hashes in a a text file /etc/shadow, which is accessible only to privileged users. Passwords are encrypted with a salt.

You could store the salt for the hashed password in another table, of course each user would have their own salt. You could then limit access to that table.

The usual approach is to use option two with email:
Store user name, password hash and email address into the database.
Users can either input their password or reset it, in the latter case a random password is generated, a new hash is created for the user and the password is sent to him via email.
Edit: If the database is compromised then you can only guarantee no sensible information can be accessed, you can no longer ensure the security of your application.

Hash the username and the password together. That way, if two users have the same password, the hashes will still be different.

This is a bit of a non problem for a lot of applications because gaining access to the database is probably the most common goal of any attacker. So if they already have access to the database why would they still want to login to the application ? :)

If the 'system' is a public website RPX can provide you with a login/user account services for the most common providers, like OpenId, Facebook, Google, etc.
Now, given the way you formulate your question I guess the 'system' you're talking about is more likely an internal windows/linux based enterprise app. Nevertheless; for those googling around for login/user account providers (like I did before a came across RPX), this could be a good fit :)

Related

What is the Security Risk of Giving Away Both the Salt and Encrypted Password?

I have inherited an app to maintain and I just discovered that when a user logs in, the returned JSON from a successfully login contains:
Primary Key of the User record in the DB
User Name
Encrypted Password
The password's Salt
It seems that having the Salt and Encrypted password voids the purpose of the salt in general.
A brute force or lookup table attack is now available again as a cracking approach.
Am I correct on this, and is there more of a threat than just that?
It's not the greatest but it is generally OK to disclose the salt. You're thinking of a pepper, which is to be kept secret.
The salted hash is not meant to prevent a brute force attack. It is meant to prevent a rainbow attack. By including the salt in the input value to the hashing algorithm, it becomes impossible to precompute lookup tables, unless the hacker creates a lookup table for each and every possible salt.
In my opinion, even when it's not something like giving away a password, you're giving away information that your front-end will not need at all and that could lead to an attacker getting the password! I mean, yes, if an attacker gets that information, he still needs an exhaustive search, with all the possible password combinations concatenated with that salt (or hashing a password dictionary with that salt), but you're giving him resources for an offline attack, and now he can try as much different passwords as he wants until he gets bored, or he gets the real password.
Someone may be thinking that it's the same as an attacker trying to authenticate with different passwords, but the main difference, is that in an online attack, you can limit the number of login attempts, so he'll not be able to try as much as he wants, while in an offline attack, he can try as many passwords as he wants.
All this could be avoided by just sending a boolean, instead of the full object and since it's not like it will require a huge refactory or something like that, I think that it's something that needs to be fixed (and you should also take a look at what he does with that information, in the worst case scenario, he's retrieving the password's hash to store it in a cookie or local storage to keep authenticating the user, or something like that).
If the salt & hash is only available from a POST to the login handler, then the damage here is very limited.
If there is some webmethod (/currentUser/getDetails) that returns the data, then this is a risk should their be any Cross-Site Scripting (XSS) vulnerabilities elsewhere on the site. Any attacker could call this method via the XSS, and then retrieve the hashed password and salt for offline cracking.
Another low risk is if the JSON response does not output anti-caching headers then another user of the same computer may be able to retrieve their password hash.
I am more concerned that the password hashes are in Hash(Password+Salt) format, rather than in a format using a secure algorithm such as bcrypt or pbkdf2.

How passwords are secured while registering it?

I have read the following article http://lifehacker.com/5919918/how-your-passwords-are-stored-on-the-internet-and-when-your-password-strength-doesnt-matter
There are a number of ways a site can store your password, and some are considerably more secure than others. Here's a quick rundown of the most popular methods, and what they mean for the security of your data.
Method One: Plain Text Passwords
How It Works: The simplest way a site can store your password is in plain text. That means somewhere on a their server, there exists a database with your username and password in it in a human-readable form (that is, if your password is testing123, it is stored in the database as testing123). When you enter your credentials on the site, it checks them against the database to see if they match. This is the worst possible method, in security terms, and most reputable web sites do not store passwords in plain text. If someone hacks this database, everyone's password is immediately compromised.
Does My Strong Password Matter? No way. No matter how long or strong your password may be, if it's stored in plain text and the site gets hacked, your password is easily accessible to anyone, no work required. It still matters in terms of hiding your passwords from, say, your friends, or others that could easily guess it, but it won't make any difference if the site gets hacked.
Method Two: Basic Password Encryption
How It Works: To add more protection to your password than plain text provides, most sites encrypt your password before they store it on their servers. Encryption, for those of you that don't know, uses a special key to turn your password into a random string of text. If a hacker were to get hold of this random string of text, they wouldn't be able to log into your account unless they also had the key, which they could then use to decrypt it.
The problem is, the key is often stored on the very same server that the passwords are, so if the servers get hacked, a hacker doesn't have to do much work to decrypt all the passwords, which means this method is still wildly insecure.
Does My Strong Password Matter? No. Since it's easy to decrypt the password database with a key, your strong password won't make a difference here either. Again: this is in terms of the site getting hacked; if you have a nosy friend or family member rooting through your stuff, a strong password can help keep them from guessing it.
Method Three: Hashed Passwords
How It Works: Hashed is similar to encryption in the sense that it turns your password into a long string of letters and numbers to keep it hidden. However, unlike encryption, hashing is a one way street: If you have the hash, you can't run the algorithm backwards to get the original password. This means a hacker would have to obtain the hashes and then try a number of different password combinations to see which ones worked.
However, there is a downside to this method. While a hacker can't decode a hash back to the original password, they can try many different passwords until one matches the hash they have. Computers can do this very fast, and with the help of something called rainbow tables—which is essentially a list of trillions of different hashes and their matching passwords—they can just look up the hash to see if it's already been discovered. Try typing e38ad214943daad1d64c102faec29de4afe9da3d into Google. You'll quickly find that it's the SHA-1 hash for "password1". For more information on how rainbow tables work, check out this article by coding guru Jeff Atwood on the subject.
Does My Strong Password Matter? In this case, yes. Rainbow tables are made up of passwords that have already been tested against hashes, which means the really weak ones will be cracked very quickly. Their biggest weakness, however, isn't complexity, but length. You're better off using a very long password (like XKCD's famous "correct horse battery staple") rather than a short, complex one (like kj$fsDl#).
Method Four: Hashed Passwords with a Dash of Salt
How It Works: Salting a hash means adding a random string of characters—called a "salt"—to the beginning or end of your password before hashing it. It uses a different salt for each password, and even if the salts are stored on the same servers, it will make it very hard to find those salted hashes in the rainbow tables, since each one is long, complex, and unique. LinkedIn is famous for not using salted hashes, which brought them under a lot of scrutiny after their recent hack—had they used salts, their users would have been safer.
By reading the above article i have the following questions in mind
1.Even if i do not have the password,i still can intercept the message digest......i dont even need the password ...i will simply launch reply attack(ie. send message digest itself for authentication after intercepting it!!)
the solution to above problem can be solved by following way
a.server genrates a random string(usually known as challenge) to the user and asks him to encrypt it with his password .....
b.user enters his password,message digest of the password is created ,random string is encrypted by this message digest
c.this encrypted string is sent to server.
d.server also encrypts random string with message digest of user,checks it with encrypted string recieved from user,if both match,he is valid user..!
2.My question is If the hacker gets access to the database,he will get access to the messagedigests/even if he does not get access to database,he can still obtain message digest while intecepting communication link when user first registers to DB......how this can be prevented??
Even if i do not have the password,i still can intercept the message digest......i dont even need the password ...i will simply launch reply attack(ie. send message digest itself for authentication after intercepting it!!)
This shouldn't be possible.
The client should send the real password to the server. It should be encrypted using SSL.
The server should hash the password and compare it to the stored, hashed password.
the solution to above problem…
That is, more or less, part of what SSL does.
My question is If the hacker gets access to the database,he will get access to the messagedigests
This is a relatively insignificant problem. The passwords should be stored as hashes with varied salts. The original passwords are protected.
even if he does not get access to database,he can still obtain message digest while intecepting communication link when user first registers to DB
Only if SSL is broken.
User registration should always be done through an SSL tunnel, so generally when following best practice you never have to worry about man in the middle type attacks.

What is the best practise for where password comparison should be performed

When authenticating a user to a website, should the hash generation and comparison be done in the database or the website?
My argument is the website should pass the user supplied password (possibly encrypted by the web server) to the database. The database then re-encrypts it with the salt and compares the hash's. The database the responds to the web server whether the user's credentials are valid or not. This way, the very minimum ever leaves the database, essentially either a yes or no, none of the stored credential info. Downside is, the database has to do more work.
The other argument is that the work should be done in the web server. Here the web server would create the hash and request the stored hash from the database and compare. In this situation the salt needs to be passed from the database back to the web server for the hash to be created. but, work is shared as # of web servers increase.
Personally I see the second method as a potential security risk. Should the web server be compromised, salts and hashes can be requested from the database and easily cracked.
What is the best practise for performing the above operation? Am I overlooking/missing something?
Thanks
The first problem I suspect you will run into (and it's a big one) is that your database does not have a password hash function. Sure, it probably has MD5() and SHA1() but these are cryptographic hash functions. Does it have bcrypt() or scrypt() or PBKDF2()?
Using a cryptographic hash function rather than a password hash function is what meant that the LinkedIn passwords could be cracked so quickly. If you don't use one of the above functions then you will be similarly vulnerable if your hashes are leaked.
Going on to answer your question assuming that your database does support a password hashing algorithm (using bcrypt simply because I have to pick one). The two alternatives are:
Hashing in the database:
$db->query("SELECT COUNT(*) FROM users WHERE username = '?' AND password = BCRYPT(?, (SELECT salt FROM user WHERE username = '?'))", $username, $password, $username);
if($row['count'] != 1)
{
// Not authenticated. Throw exception.
}
In this case, the raw password is sent to the database and a simple yes or no (1 or 0) is returned. This database communication can be encrypted. The hash and salt are never held in the application.
Hashing in the application:
$db->query("SELECT username, salt, password FROM users WHERE username = '?', $username);
if(bcrypt($password, $row['salt']) != $row['password'])
{
// Not authenticated. Throw exception.
}
In this case, the hash and salt are pulled from the database into the application and the hashing of the raw password and comparison is done there. The communication to the database can still be encrypted. The raw password is never held in the database memory.
For efficiency, we can assume that both hashing algorithms are written in C (or some compiled language) and are possibly provided by the OS so take the same time. The application hashing option receives more data over the wire and the database hashing option sends more and has a more complex query (essentially two queries, one to get the salt and one to effect the comparison). It may not be possible to use an index the way I have written that query but the query could be rewritten. Since the size of the data in both cases is likely still one TCP packet, the speed difference will be negligible. I would call this one a win for the application hashing option due to the subquery.
For exposure. I would consider the raw password to be more sensitive than the hash and the salt together. Therefore, limiting the exposure of the raw password seems like the safer bet, making application hashing the best practice.
There's a really good article on how to store passwords securely here:
http://throwingfire.com/storing-passwords-securely/
You are overlooking the purpose of a salt.
A salt is used to prevent a dictionary attack against hashed passwords. If your password is "peanut" and hashes to 12345, then I can pre-generate a list of hashes for every word in a dictionary (including your password) and quickly find your password by doing a lookup against my pre-generated set of password hashes. This is what happened to LinkedIn recently. If the passwords are salted, I'd have to pre-generate a dictionary for each salt value after compromising the database, which would be prohibitively expensive.
Furthermore, proper randomly-generated salts prevent an attacker from knowing that you and I have the same password (without the salt, we'd have the same hash).
My point is that the salts are not intended to be a secret. They are not public information, but an attacker getting access to the salt values + the hashes does not necessarily mean that the passwords have been compromised.
A good rule of thumb for computer security is that if you have to ask, you shouldn't do it yourself. But if your concern is exposure of password details if the web server is compromised, then one approach is to move authentication onto its own system, and don't give the web server access to the password database at all.

Why aren't original passwords stored?

I am new to web development. Am I allowed to store users' original passwords? I know good practice is to store the hashed password using a salt, but why don't we store the original password?
Is it because the database is easily hacked, so hashing protects passwords? Are there any other reasons? If not, I would like to store the original password if it is legal to do so.
The legality depends on the country you live in. But there are best practices, too. And a best practice is to encrypt user's passwords. In this way, if someone breaks into your database, they will not be able to obtain the long list of passwords, and try each one of them in ebay, yahoo mail, and gmail. Users generally use the very same pair of username and passwords for many sites.
As Jon points in the comment, of course there is difference between hashing and encrypting. Hashing is a one-way, data-destructive process, which takes an arbitrary-length string as input, and outputs a fixed-length string. This string is defined in such a way, that changing any single bit in the original input, will cause the hash to be different. If you have a hash, therefore, it is not possible to reconstruct the original text (i.e. it is not possible to recover the password).
On the other hand, encryption proper is a technique where you can recover the original password, knowing secret keys, passwords, etc.
Usually, you want to hash passwords, not encrypt them: it's not necessary, and it is more complex to setup. You are not supposed to recover password either: you will just regenerate them.
Imagine if Facebook was hacked, it didnt encrypt any of the user's passwords. Facebook itself has around 200 millions(?) users
What if all of the 200 million passwords were leaked to some evil organization? Many users use same password as their mails or any other sensitive online services such as bank accounting.
Facebook wouldn't be safe at all once. Would you register an account there?
I don't know if it's legal, but nonetheless I would advise against it for at least three reasons:
This is not only about hackers getting access to your passwords. Users often have the same password for multiple accounts (also they shouldn't have). So who says we can trust you or other people who have legal access to this data?
It doesn't matter how secure you think your server is. There is no such thing as absolut security for a server. You should consider that it could be hacked eventually. And don't believe it'll never happen. Hope for the best, but always plan for the worst!
I would use every easy and cheap security I can get to secure not only my data, but also the data of the users. And the method of using a salt+hash is cheap. It will cost you 2 lines of Code. It
Yes, it's perfectly legal, though absolutely not recommended to store passwords in plaintext. And it's not that your actual live database can be compromised: even a backup copy can be stolen (without you ever knowing it).
When passwords are stolen, this is very bad for your actual users, since very few of them actually use different passwords for different sites.
It is legal according to the law. Some companies store the password in plain text, so that it is recoverable.
However, for safety reasons this is a bad idea. Once in a while, some company gets hacked and their database is accessed. In some cases, this exposes the passwords of thousands of users. This will severely damage the image of your company, and is even more a security risk when the password is not hashed.
If you want the password to be recoverable, at least encrypt it so that it is not easily viewable by accessing the database.
The original password isn't stored because once the database has been hacked your vulnerable information is at risk including your password so encrypting will not do anything once they have access through other sources. Depending on where you live some sites will store your password in plain text, For example, if your password is Appletree1234 they will stored your password in plain text as Appletree1234. According to Lifehacker.com, when you enter your credentials on the site, it checks them against the database to see if they match.

How does hashing and salting passwords make the application secure?

As much as I understand it is a good idea to keep passwords secret from the site administrator himself because he could try to take a user's email and log into his mailbox using the same password (since many users use the same password everywhere).
Beyond that I do not see the point. I know it makes more difficult the dictionary attack but... if someone unauthorized got into the database, isn't it too late to worry about passwords? The guy has now access to all tables in the database and in a position to take all the data and do whatever he wants.
Or am I missing something?
The bigger problem is that people tend to use the same password everywhere. So if you obtain a database of usernames and unsalted passwords, chances are good they might work elsewhere, like hotmail, gmail etc.
The guy might be in a position to do everything he/she wants to your system, but you shouldn't allow him/her to do anything with other systems (by using your users' passwords).
Password is a property of your users. You should keep it safely.
Many of your users use the same credentials (usernames/passwords) at your site as they do at their bank. If someone can get the credentials table, they can get instant access to a bunch of bank accounts. Fail.
If you don't actually store passwords, then attackers can't steal your users' bank accounts just by grabbing the credentials table.
It relies on the fact that a hash is a one way function. In other words, its very easy to convert a password into a hash, but very difficult to do the opposite.
So when a user registers you convert their chosen password into a hash and store it. At a later point they login using their password and you convert the password to its hash and compares it this is because, to a high level of probablity if (passwordhashA == passwordhashB) then passwordA=passwordB.
Salting is a solution to a related problem. If you know that someones passwordhash is, say ABCDEF, then you can try calcuolating hashes for all possible passwords. Sooner or later you may find that hash('dog') = ABCDEF, so you know their password. This takes a very long time, but the process can be speeded up by using pre-created 'dictionaries' where, for a given hash you can look up the corresponding password. Salting, however means that the text that is hashed isnt a simple english word, or a simple combinationofwords. For example, the case I gave above, the text that would be hashed is not 'dog', but is 'somecrazymadeuptextdog'. This means that any readily available dictionary is useless, since the likelyhood of it containing the hash for that text is a lot less than the likelihood of it containing the hash for 'dog' This likelihood becomes even lower if the salt is a random alphanumeric string.
The site admin may not be the only person who gets access to your password. There is always the possibility of a dump of the whole database ending up on a public share by accident. In that case, everybody in the world who has internet access could download it and read the password which was so conveniently stored in cleartext.
Yes, this has happened. With credit card data, too.
Yes, it is highly probable that it will happen again.
"if someone unauthorized got into the database, isn't it too late to worry about passwords?"
You're assuming a poor database design in which the authorization data is comingled with application data.
The "Separation of Concerns" principle and the "Least Access" principle suggest that user credentials should be kept separate from everything else.
For example, keep your user credentials in an LDAP server.
Also, your question assumes that database credentials are the only credentials. Again, the least access principle suggests that you have application credentials which are separate from database credentials.
Your web application username and password is NOT the database username and password. Similarly for a desktop application. The application authentication may not necessarily be the database authentication.
Further, good security suggests that access to usernames and passwords be kept separate from application data. In a large organization with lots of database users, one admin should be "security officer" and handle authentication and authorization. No other users can modify authorization and the security officer is not authorized to access application data.
It's a quick audit to be sure that the security officer never accesses data. It's a little more complex, but another audit can be sure that the folks with data authorization are real people, not aliases for the security officer.
Hashed passwords is one part of a working security policy.
Of course, storing hashes of passwords instead of plain-text does not make your application secure. But it is one measure that increases the security. As you mentioned if your server is comprised this measure won't save you, but it limits the damage.
A chain is only as strong as its weakest link
Hashing passwords is only strengthening one link of the chain. So you will have to do more than that.
In addition to what has already been said regarding salting, there's another problem salting solves :
If you use the same salt everywhere (or no salt at all), it's possible to say just by looking at the database that user foo and user bar both have the same password (even if you don't know what the password is).
Then, if one achieve to get foo's password (using social engineering for example), bar's password is known as well.
Also, if the salt is everywhere the same, one can build up a dictionary dedicated to this specific salt, and then run a brute-force attack using this 'salted' dictionary.
This may be a bit off topic, but once in a while, I notice some websites are not using hashing (for example, when I click the forgot password button, they send me my password in cleartext instead of allowing me to chose another one).
I usually just unsubscribe, because I don't think I can trust a website designed by people not taking the elementary precaution of hashing passwords.
That's one more reason for salting:)
People seem far too complacent about this! The threat isn't some guy with shell access to your system or to the backup media, it could be any script kiddie who can see the unprotected (but dynamic) part of your site(*) and a single overlooked SQL injection threat. One query and suddenly he can log in as any user, or even as an admin. Hashing the passwords make it far less likely that the attacker can log in as any particular user using their password -or- update a record with their own password.
(*) "unprotected" includes any part of the site that can be accessed as a self-registered user. Contrast this to a bank site, for instance, where you must have an existing bank account to gain access to much of the site. An attacker could still open a bank account to gain access to the site, but it would be far easier to send big guys with bigger guns after him when he tries to crack the system.

Resources