I'm aware passwords should be hashed/salted on backend and HTTPS should be used for transportation. My concern is that, on account registration, there is a section of code where the plain text password could exposed by way of a poorly placed log-statement.
I understand hashing passwords multiple times is not ideal, but to address this concern would it be acceptable (from a security governance perspective) to also hash the password on the frontend?
No, as password hashing should use salt and a suitable (slow) hashing algorithm, implementing this correctly and in the future double hash all passwords would require a lot more work than masking the password in the log.
If you use an unsalted hash with a fast hashing algorithm many passwords can be quickly broken using modern hash cracking equipment.
Also see Does it make security sense to hash password on client end
Related
A friend of mine and me are having a discussion about whether we should pre-hash the passwords of the users of our webapp before sending it to our servers.
I know that there are multiple questions that already handle this topic but they're all about transferring it securely to the server. Our idea is not about the transfer security (we use SSL) we want to hash clientside to prevent that the "real" passwords reach our server.
The idea came as Twitter announced their bug that caused passwords to be printed to a logfile in cleartext.
We are currently discussing about whether this concept makes sense or not and how it affects the security of a password (in terms of Bruteforce) if we would hash it with SHA512.
TL;DR:
We want to hash passwords clientside to prevent our servers from getting them in cleartext (we use SSL for transfer).
Does this make any sense?
What algorithm would be best to use for hashing?
The hashed passwords would then serverside be hashed again with bCrypt.
It 100% makes sense: in fact, the concept has been proposed by a number of people, but the difficulty is in implementing correctly. There are a number of pitfalls if you do it wrong, the most direct one is being vulnerable to "pass-the-hash" as #swa66 describes. To prevent that, you need to hash on both sides. The client-side hash should be slow (bcrypt, scrypt, argon2, or pbkdf2) whereas the server side hash should be fast (sha256).
EDIT: A number of people have down-voted this without understanding how this works, so I now include the basic details here (previously I only linked to how this works). The idea is to apply a slow hash such as bcrypt on the client side, and then a fast hash such as SHA256 on the server side. The fast hash is required to prevent pass-the-hash attacks. In the event of the database leak, an attacker either hash to invert the fast hash (impossible -- violates the one-way property of a cryptographic hash function), or brute force the preimage to the fast hash (impossible -- the size is the length of the output from the slow hash, for example 184-bits for bcrypt), or brute force the combination of the slow hash and the fast hash -- which puts the attacker back at the same position as if the entire computation had happened server side. So we have not reduced the security of password attacks in the event of a database leak by shifting the heavy computation to the client side.
I've surveyed a number of proposals like this in Method to protect passwords in databases for web applications. Additionally, I analyse the pros and cons and identify weaknesses that have not been identified before (account enumeration), and propose a unique way of doing this securely. The research is built off a number of sources, including:
Secure authentication: partial client-side key stretching… please review/criticize my idea
How to securely hash passwords? -- see section on Client Side Hashing
Client side password hashing
Discussion from various authors on Hacker News -- see comments from oleganza, mschuster91, crusso, etc...
You cite the Twitter example, and GitHub did similarly. When I wrote the paper above, the most prominent example for preventing a server from seeing the clear text passwords was Heartbleed, which I comment on in the paper (bottom of Section 1.3).
There has been subsequent follow up research by others identifying similar ideas -- Example: Client-Plus-Server Password Hashing as a Potential Way to Improve Security Against Brute Force Attacks without Overloading the Server. No one person deserves all the credit, but the main takeaway is yes it is a good idea if you do it securely, but you really need to understand the risks (it is easy to do insecurely if you have not read the research).
While #swa66 outlined how to manage passwords securely, let me note that there is a valid scenario where you can consider client-side password hashing, so don't just blindly follow "best practice", try and understand it first.
Let's say I have a standard web application that stores data from users. In my threat model, I don't even want my own users to have to trust me, or in other words, I want my users' data to be secure even in case of a full compromise of my servers. Therefore, I let them choose a password, and encrypt their data on the client, before sending it to the application. They can retrieve their encrypted data with their user id. Well, that doesn't sound very secure, I can just download anybody's encrypted data and run offline attacks against it. So let's have them access their encrypted data with their password (I don't want them to have to remember two different passwords). But that's not good, because I have their password then to decrypt their data. So one simple solution is to encrypt their data with their password, and send it to the server along with their hashed password, which as it's correctly noted in the answer is the new password as far as the server is concerned (so the server should store it hashed once again and so on). However, the server has no way to decrypt client data, because it never has the original password, yet only the valid person can download even their encrypted stuff, and they only have to remember one password. (Note that this is a very much simplified model, in reality, much more is needed, like for example a proper key derivation function, not just plain hashes, but that's another, much longer story.)
Don't get me wrong, I'm not saying you should normally be hashing passwords on the client - no, the other answer is the correct one in that regard. I just wanted to show that there is at least one use-case where client-side password hashing is a valid option. See well-known password managers, some work similarly.
NO!
Rule one in cryptography: do not invent it yourself, you'll make horrible mistakes.
It's not against you personally, by far not: even top notch experts make mistakes when designing with great care new systems. That's why they peer-review each-other's work multiple times before anything become a standard. Many proposals for such standards by such experts get redrawn due to problems detected during such a peer-review. So why can't the rest of us mere mortals design: there's nobody good enough to do the peer-review as the experts will not touch it.
Hashing the password client side
Hashing client side is really bad as the hash becomes the password, and now you store it on the server in the clear.
How to do passwords
Only store hashed passwords (implied: send the password to the server, just do not store it)
use a salt and store it with the password (unencrypted). The salt is essentially a random string that you concatenate to the pasword before you hash it (to store it , and to verify it)
Use a SLOW hash. Using a fast hash is a common and fatal mistake, even when using salts. Most hash functions people know like SHA-256, SHA-3 etc. are fast hashes and completely unsuitable for hashing short, predictable items like passwords as they can be reversed in a surprising short time.
How slow: as slow as you can afford. Examples of slow hashes:
bcrypt, PBKDF-2 (which is essentially a high number of rounds of a
fast hash to make it slow)
There are -depending on your programming environment- pre-made routines, use them!
Ref:
https://crypto.stackexchange.com/questions/24/what-makes-a-hash-function-good-for-password-hashing
https://crypto.stackexchange.com/questions/59797/authorities-on-password-hashing-best-practice
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.
I have just pressed 'forgot password' on hosting24.com, only to have my password emailed to me in plain text (see image below). I contacted their technical support to question this and they have told me:
We are using Salt encryption on our website, passwords are not stored
in plain text. Please let us know if you have any concerns regarding
the security of your data.
The way I understand it, is that once a password is 'salted' it cannot be reversed back to plain text. I am also very concerned, considering their partner company 000webhosting was victim of a massive hacking incident recently, which exposed that their security was sub-par.
Thanks.
EDIT:
After a few heated emails I finally got this response:
Our passwords are encrypted with a secure encryption method in the
database. Although we do have a decryption method in place (that is
used to prevent fraud), all this is going to change as we are
re-designing the project and updating the code to adhere to new age
standards. We are sorry to have let you down on this one.
Please contact us with any additional questions. Happy holidays!
'New age'. Amazing.
EDIT:
I sent the website this link to prove a point, so I anticipate a load of down votes from their tech support.
Salted hashed passwords are not directly reversible—that's the point of hashing. However one can always try to recover them through brute force, trying all possible/likely passwords to see if the hash matches.
How expensive that is to do depends on the strength of the hash used, but you would never build a system that stores and decrypts passwords that way. If they said they were storing only salted hashes, and still were able to send you the password you originally set yourself, they're clearly lying.
They don't mention hashing though:
We are using Salt encryption on our website, passwords are not stored in plain text.
“Salt encryption” isn't a thing, but let's be as generous here as we can.
It is possible they mean they're using reversible encryption with some randomised element (variable IV, or extra data in the encrypted message) which would ensure two passwords don't get matching encrypted versions (ie the same purpose as the ‘salt’ in a hashing operation).
It's also conceivable that there could be some valid reason why they need reversible passwords, for example if they need to use the passwords to authenticate to another separate system. It's possible to build reasonable systems with reversible passwords, but compared to Good Old Bcrypt it's a whole lot more effort to manage this way (eg keys on the application server; wide-ranging internal policies to manage that; HSMs; and watertight code auditing).
Let's say we accept that this is what they've done and they've implemented it solidly (which is highly doubtful—much more likely they've got plaintext passwords or a hacked-up and vulnerable AES). Even then, they've then blown it by sending you the reversed password in a mail over the unencrypted public SMTP infrastructure.
There are things you can do to mitigate the untrustworthiness of the mail channel, such as sending a single-use token or temporary password that requires a new password to be set afterwards. But there is never a good reason to send an existing password, that will continue to work on the target site and which you might have used to secure other services. User-set passwords should never touch SMTP.
No, they can't without astronomical computing power. I'd bet large sums of money that they have a second database of plaintext passwords.
does using hash functions and algorithims suffice the need to encrypt the data, while communicating with the server
I am applying salt mechanism in my project and I will be concatenating the salt with the entered password, and then hash them all.
do I still need to encrypt the result?
The usual workflow for a website to transmit user passwords looks like this:
The client sends the password plaintext to the server.
The transmission is done with an encrypted connection (HTTPS/SSL), to prevent a ManInTheMiddle attack.
The server calculates a hash of the plaintext password, and this hash is then stored in the database. It is not necessary to encrypt the hash any further.
Make sure you use a random unique salt for each password, and a slow hash function with a cost factor for hashing passwords. Good algorithms are BCrypt, PBKDF2 or SCrypt.
Storing passwords
To store user passwords securely, you need 3 things:
Do not store the plain password, store a hash instead
The hash makes it extremely difficult to recuperate the password even if an attacker manages to capture the entire database
To prevent the use of rainbow tables, you need a salt
The salt is stored in the clear (can be along with the hash) and is random, one for every user and you can easily chose a few one whenever the user changes their password.
You need a SLOW hash, not a fast hash
What are fast hashes: MD5 (consider it broken), SHA-1, SHA-2, ... are unsuitable as the attacker can perform them too fast and use dictionary attacks to try common passwords and find that way up to 95% of you user's passwords in mere hours on modern rigs.
How slow does it need to be ? As slow as you can afford.
And there's a rule 0: Do not invent crypto yourself, you will make serious mistakes before you know it.
Other privacy sensitive info
You're most probably also storing other sensitive information of your visitors in addition to the passwords (email addresses, IP addresses, names, postal address, ...), CC numbers (you better not go there), ...
You need to protect that as well and using hashes isn't the way to do that in most cases. Some of these have requirements and regulations of their own (e.g. Credit Card data is regulated by the issuers who'll force you to be compliant with PCI-DSS).
In essence you need to do a risk analysis and manage that risk by either accepting it ("so be it"), transferring it ("get insurance"), avoid it ("we're not storing that"), or mitigating it ("we're going to improve our way of working").
encryption
Why the media will make you believe there's a "magic" solution in that incomprehensible "encryption" thing, in reality it needs to be done right and in the right conditions to have any meaning at all.
E.g. If you encrypt the entire disk of a server: it will not protect you from an attacker abusing your server scripts and getting to the database (as the database engine and webserver scripts have access to the decrypted disk already)
So, you really need to go back to the risk analysis and chose the measures there instead of getting ahead of yourself and suggesting encryption as a tool that's unlikely to help you for your biggest risks.
I have read about password salting, but this might sound a little odd. But how do I store and secure the salt. For example in a multi tire architecture say I use the client machine’s GUID to generate my salt then the user gets restricted to a single machine but if I use random salt it has to be stored somewhere. Few days back I saw an sample application where the hash and the salt was generated on the client system whenever a new user was created and then the salted password and the hash is transmitted to the server where they are stored in SQL server. But if I follow this method and the database is compromised the passwords and the salt values for each password will be available to the X person. So, should I again salt/encrypt the passwords and received salt on server side? What is the best practice of salting?
Storing the salt unencrypted in the database next to the hashed passwords is not a problem.
The purpose of the salt is not to be secret. It's purpose is to be different for each hash (i.e. random), and long enough to defeat the use of rainbow tables when an attacker gets his hands on the database.
See this excellent post on the subject by Thomas Ptacek.
edit #ZJR: even if the salts were completely public, they would still defeat the benefit of rainbow tables. When you have a salt and hashed data, the best you can do to reverse it is brute force (provided that the hash function is cryptographically secure)
edit #n10i: See the wikipedia article for secure hash function. As for the salt size, the popular bcrypt.gensalt() implementation uses 128 bit.
Please take a moment to read this very good description of salts and hashing
Salt Generation and open source software