Is storing a permanent access token as good as storing password? - security

If I want to persist the users' login such that they do not have to re-login even after, say 1 year of inactivity, then is storing a permanent access token as good as storing the password directly (perhaps hashed), since the (permanent) access token would essentially be the "alternative password"?

Storing an access token is surely safer than storing the password directly, but let's see why:
An attacker can only get this token, but not the original password. This is better, because passwords are often reused on other sites, and/or can reveal password schemes. ➽ Make sure the token is random and not derrived from the password.
The token is not just another password. While passwords choosen by a user are often weak, a token is very strong. They are so strong, that brute-forcing is impractical. ➽ Generate random, long enough tokens, they should be at least 20 characters a-z,A-Z,0-9.

Generally speaking, yes. But, with a lot of caveats.
A long, random token, generated by a CSPRNG (this is very important, there are different ways to generate "random" strings and not all of them are really random), is stronger than a password - yes. However, the way you intend to use this token means that it is effectively a password by itself, and that means the same criteria applies:
It can't be permanent.
A key property of passwords is that they are not constants and users can change their passwords when stolen, or otherwise over time. Any kind of token should be no different, except that it should be automatically changed (rotated) by your application, on regular intervals.
It MUST be hashed!
(with a strong algorithm: bcrypt, scrypt, Argon-2I, PBKDF2; anything else is plain wrong)
Don't ever store user passwords in plain-text format, anywhere. Even if it is guaranteed that the user doesn't use this password on any other site, a plain-text password means that anybody who gets their hands on the database (even for a brief time), can hijack user accounts.
You have a responsibility to protect your users not only from "hackers", but from yourself as well.
Don't store it in a cookie, even if hashed or encrypted.
The way you've worded the question implies that you would do something like this. Cookies are not a secure location to store passwords of any kind. Temporary, short-lived tokens - sure, but not passwords.
It looks like you're trying to design your own authentication protocol, which is not an easy thing to do. It may be easy to make it work, but that's about 5% of the job; there's just too many details to consider. And all of this, for the tiny benefit of saving the minor inconvenience of a user typing-in their password once in a while - people are used to this; it's not worth the security risks.
In case you are hell-bent on providing long-lived logins, I would recommend using an existing authentication protocol. Every such protocol uses on cryptographic signatures, avoiding reliance on user passwords altogether and thus eliminating all of the above problems almost entirely.
Personally, I would just allow the so-called "social logins" - via Facebook, Google, Twitter. You wouldn't have to handle passwords at all, and anybody can login with a single click of a button.

Is better to store an access token than storing the password or the hashed password (can always try brute force to find the password) and I think you should give a token a lifetime.

Although the answer is yes, but it also depends on the place you are storing the token. And you might want to auth the user with XSRF/CSRF token as well along with the token.
But storing token is better than storing password.

Related

Why not using current hash password to sign the reset token?

I have read through many guides about best practice to create a user reset password token. They're all saying that we should create another database table and store the hashing of the token.
And it comes to my mind that why don't we just re-use the current hash password to sign the reset token? We email the user with that token, then check if they are match.
If the user changes the password, the token would be invalid then so it makes sure one time use. So now we don't have to add extra table.
Not sure if I miss something here?
Well, you wouldn't introduce a major and directly exploitable vulnerability by doing so, but consider a few things to see why I think it wouldn't really be recommended.
The password hash is known to anybody that knows the password. It's probably not the actual user, but what if as an attacker, I don't want to directly try passwords because that's too noisy, gets into logs, provokes alerts and so on. Instead, I make the user change their password somehow (eg. as a man in the middle I intercept all login responses or whatever, it doesn't matter how) and then I guess their password by trying to change it, knowing the only secret that was used for the token. This might corrupt auditability at the very least.
Also crypto algorithms sometimes have weaknesses. Not very likely, but one such weakness might allow finding out bits of the key if enough ciphertexts or hashes (some potentially with plaintexts) are known. You don't want an attacker to ever be able to find out user passwords, especially because those tend to be reused unfortunately.
So basically it's all a bit subtle, maybe only a building block in a complex attack, but you shouldn't use secrets beyond their purpose. If you do so, weaknesses will be linked together, weakness of one component (password reset in this case) will become the weakness of another (password storage). It's better to keep separate things separate and thus kind of compartmentalize their vulnerabilities (reduce impact of an exploit if you like).

Hashes or tokens for "remember me" cookies?

When it comes to remember me cookies, there are 2 distinct approaches:
Hashes
The remember me cookie stores a string that can identify the user (i.e. user ID) and a string that can prove that the identified user is the one it pretends to be - usually a hash based on the user password.
Tokens
The remember me cookie stores a random (meaningless), yet unique string that corresponds with with a record in a tokens table, that stores a user ID.
Which approach is more secure and what are its disadvantages?
You should use randomly generated tokens if possible. Of course, the downside is that you have to write some extra code to store and use them on the server side, so this might not be warranted for all web applications. But from a security standpoint, this has distinct advantages:
An attacker cannot generate tokens from user IDs, but he can definitely generate hashes. This is a big problem, even if you use salt when generating hashes (and you should), your users are screwed if the salt ever gets into the wrong hands.
Giving out these tokens enables your users (or your admin if need be) to "log out" certain sessions that they might want to get rid of. This is actually a cool feature to have, Google and Facebook use it for example.
So, if you have time and budget: tokens, absolutely.
Typically you keep the token -> user mapping secure on the server side. So ultimately your security is all based around keeping the token safe and ensuring that its lifetime is controlled (e.g. it expires and/or is only valid when given to you from the same IP as that used by the original provider of the credentials - again, just an example)
Security of token based authentication
Hope this helps.
Yes tokens would be more secure if they produce a random string each time.
On the other hand, the whole point of remember me is that the user doesn't have to log in again, so unless they click log out your rarely going to need to re-produce a new token unless it expires.
I guess you should stick with tokens and not sacrifice security for lazyness :-p

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.

Is it advisable to store a hashed password in a cookie?

I want user's to be able to select a "remember me" box on my website so they need not log in each time they come. So, I need to store a unique ID in a cookie to identify them. Is it safe to hash their password with sha512 and a long salt in PHP and store that value in the cookie?
If the cookie was stolen, would their password be at risk?
Obviously it must be connected to their password somehow, otherwise if the cookie value was guessed or stolen, the user would not be able to stop someone else logging in.
Also, is it advisable to use a GUID at all as the unique identifier?
Thanks,
Ben
Remember, the hash of the password is effectively the same as their password. Somebody who stole the hash would have the same access to the user's account as if they had stolen their password. Therefore it is not advisable to store a hash of the user's password in a cookie unless there was some other information not stored with the cookie that is used to authenticate (i.e. 2-factor authentication).
Here is an excellent article on this very topic. Many of the answers to your question are hitting on techniques outlined in it.
There's a low risk with a good algorithm and large salt, but why take any unnecessary risk?
If you just need to identify the user, then store something that can uniquely identify the user, like a guid along with some other stored verification code (not their password, some random long string). I wouldn't use a guid alone as it would not be a safe method of authentication.
It wouldn't hurt to have some kind of "password" in the cookie along with a user id (to prevent users from changing the uid to that of another user), just don't make the "password" the same as the actual user's password.
And just because it's a hash doesn't necessarily mean it's one-way (well, by definition it does, but there are utilities to generate MD5 plaintexts and I would guess it's only a matter of time before it happens to others). I would hash some kind of secondary password.
An alternative way of doing this might be use the cookie as an encrypted storage for only indirection data. You'd need some sort of unencrypted identifier that would serve as a pointer to the key (or the required information to derive the key) in the application's database, followed by a blob encrypted by the key obtained from the identifier, which itself would contain some sort of one-time-usable identifier that authenticates the session.
Given the following assumptions:
Your database is secure (e.g., your application can access it, but your user cannot directly do so, and also assuming that the application has been proofed against SQL injection)
Your salts are strong; that is, reasonably high-entropy enough that attempting to crack the salted password is infeasible even if the password is known
Then what this would provide is a method by which one can be reasonably certain that the session is not able to be hijacked or stolen in any way. That is to say that a copied cookie is only of limited usefulness, since the user must not have used the cookie between its theft and usage by an attacker.
While this protects against replay, it also means that if someone does manage to steal the cookie at exactly the right time, and manages also to use it before the original, legitimate user does, the attacker now is in control of the session. One can limit a session to an IP address to mitigate that risk (somewhat; if both the user and the attacker are behind the same NAT, which is the most likely scenario in any home or small-to-medium business network) then this point is pretty moot, since the IP address would appear to be the same anyway. Also useful might be limiting to the current user agent (though that can break unexpectedly if the user updates their browser and the session does not expire at browser close time), or finding some method by which one can identify the computer that the user is on just well enough that there is reasonable certainty that the user hasn't moved the cookie from one system to the next. Short of using some binary plugin (Flash, or Silver/Moonlight), I'm not sure that the latter is possible.
To protect against a permanent session hijacking, require that the user to reauthenticate him- or herself periodically (e.g., limit the allowed session lifetime or require something like a token/fob/dongle) and require that the user reauthenticates him- or herself upon entering sensitive areas of the application, such as password change and potentially dangerous actions, patterns or behaviors such as the deletion of data, unusual usage patterns, bulk actions, and so forth.
It is difficult to secure applications and yet retain their ease-of-use. If done carefully, security can be implemented in a manner which is minimally intrusive and yet still effective—well, for most Internet-facing applications, anyway.
It's not advisable, but if your gonna do it, at least salt your passwords before you do so. This will stop people from using hash crackers if they do manage to get hold of your visitor's cookies.

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