If the input for the security question is completely digital, should the answer to a security question be hashed (or at least encrypted) on the authentication server?
-
14Does anyone else hate security questions? – user606723 Aug 17 '12 at 19:35
-
1You mean hashing by the way, not encrypting. Encryption can be reversed in the case of a compromised server, one of the cases you're trying to protect against, and thus adds little security. – Luc Aug 17 '12 at 23:51
6 Answers
I'll assume the model you're trying to defend against is where an attacker has access to the database. If that's the case, yes, it's a bad idea if an attacker can compromise an account by only knowing those details.
My advice would be to convert the answer to uppercase, then salt + hash it. Optionally also trim it or collapse all whitespace. This provides a reasonable security measure without reducing usability.
- 132,208
- 43
- 298
- 379
-
4Ok let's not defend ourselves against a case where an _attacker_ has access, but what can all _admins_ do with the security question info? How many sites ask for the same data? – Luc Aug 17 '12 at 22:07
-
@Luc: If the "security" question is "What's your zodiac?" or "What's your pet's name" then its as good as ROT13. – Hubert Kario Aug 19 '12 at 01:52
-
Can the salt be the same one used for the password or should it be different? Can all security questions use the same salt or should each have a unique salt? – yitzih Jul 26 '17 at 19:23
-
1@yitzih There's no reason to reuse the password's salt. (And if the password changes and its salt changes too, then you'd either have to re-hash the security answers or store the salt additionally somewhere else...) You should use a library like bcrypt which stores the hash and salt together in one string. There's no need to keep them separately or re-use salts. – Macil Jul 26 '17 at 22:02
If those questions provide the same level of access as the password, then for all practical purposes they are a password and should be treated like one. Apply the same level of protection to all passwords that you store.
- 1,832
- 12
- 19
-
5And even if they don't provide the same level of access, you should still hash it. See Lekensteyn's answer. – Luc Aug 17 '12 at 22:04
The answer is yes, you should always hash this.
Why do we hash stuff like passwords at all? Two reasons: mainly because people often use the same password for many different things, and additionally (it's more of a fortunate side-effect) to prevent attackers from logging in when they obtained read-only database access.
So don't you think the user's first pet or mother's maiden name is also data that he would use across multiple services? Or that could potentially be used for social engineering attacks? Or could be used to reset the password and also gain access?
For that reason, you should protect answers to security questions against attackers (and admins!) the same way as you do with passwords.
Why not encrypt it?
Encryption is reversible, it makes it possible to access the data while there is no need to. One of the cases you're trying to prevent by protecting the database data, is a case where the server is compromised, or where an insider has bad intentions. In both cases, they could use the decryption key to reverse the protection. With decent hashing, this is no longer possible.
But what about punctuation? You can't match a hash unless it's exact.
People might use multiple words in an answer, and one time they might use capitalization, other times they might remove spaces between words or put a period behind the sentence... so I'd suggest normalizing it to at least remove spaces, remove punctuation and lowercase any capital letters.
Regardless of whether you have it stored plaintext or encrypted, you need to write a normalisation algorithm to compare them anyway (so that does things like lowercasing). That algorithm will boil it down to a basic version to be able to decide whether it a match. If you apply that before hashing the result, it will work just the same.
PS. Don't do security questions. They're super bad for a lot of reasons. But if you do use them, then at least protect your users a little bit and hash the answers.
- 31,973
- 8
- 71
- 135
As mentioned by @Polynomial and @B-Con, storing the security questions unencrypted is dangerous if those can effectively be used as password. But even if this was not the case, you should not store the security answers unencrypted.
Common security questions ask for personal details, like "What is your mother's name?" (assuming a system where you cannot put custom questions in or where the user just picks one of the existing questions). You are not the only server that may ask for that detail, the same information can be used to compromise information on other systems that have the same security questions and answers.
- 5,898
- 5
- 37
- 62
Although there is an accepted answer and a consensus that it should be hashed, it is worth noting that there are cases where that might not be desirable.
The most obvious one is where you are asked for selected characters from the answer. This provides protection against replay attacks. But you can't verify the response against hashed data without storing every possible hashed combination - and as a result you make it much, much easier to brute-force the clear text (i.e. you loose the benefit of hashing). Typically this approach is used in conjunction with a (hashed) password for authentication.
A further case where this might be applicable is where you might want to provide some lassitude in the validation, for example permitting variations in capitalization. A use case for this would be for a token which is used infrequently, e.g. in a password reset, but should be applied with caution and in conjunction with other controls (e.g. sending a reset token to the registered email address rather than allowing an immediate password change).
These are security trade offs. But perfect security is expensive and gets in the way of the thing users want to do.
- 18,278
- 39
- 73
The most secure way where password can only be reseted if secret answer is known do the following:
x={hash(password)}priv_S
where priv_S is the secret answer(private key) and public key(pk_S) is stored.
And to verify do:
I=user's typed secret answer
x=={{x}pk_S}priv_I
To login:
$username=<username>&&$hash=={x}pk_S
This allows the ability to only change the password if the secret answer is known but allows to login without it.
- 15,436
- 5
- 45
- 50
- 1
- 1
-
This doesn't make sense to me. You are setting x to something and comparing it with something else. – Limit May 12 '18 at 00:17
-
nope {x}pk_S = hash(password) as they are inverse functions so they cancel out, and the statement will only be true if `priv_I` = `priv_S`. – Dev_anon101 May 12 '18 at 00:31
-
Well, first of all secret answer cannot be a private key. and by your logic you are storing x as the plaintext password because applying your public key on the password and then applying private key on it will simply return the password in plaintext – Limit May 12 '18 at 00:35
-
4This answer is difficult to make sense of in its current form. Your notation is unclear, and there's no explanation as to why public key cryptography is relevant in the first place. – AndrolGenhald May 12 '18 at 00:36
-
@Limit password is not stored in any way just the hash applying public key will only give you the hash (this is required for login). – Dev_anon101 May 12 '18 at 00:38
-
I am sorry but I am not able to understand why you mean by hash applying public key will only give you the hash required for login. Are you storing the password by hashing it with the public key? – Limit May 12 '18 at 00:41
-
@AndrolGenhald which notation are not clear? public key cryptography allows the ability to implement something which requires you to enter a secret key even at database level as well as login without it like normal. As the first sentence says this implementation is only valid for something where user is required to know their secret answer at all cost and not retrievable by anyone. – Dev_anon101 May 12 '18 at 00:44
-
@Limit normally password is hashed (with salt or any other methods but never raw). All I am doing here is signing this by using the private key which in this case will be the secret answer. Therefore the public key will only give you the hash. Changing the hash is possible but login will fail as you need to sign with the private key which only the user knows. The correct way of changing the password can only be done with the users secret key. – Dev_anon101 May 12 '18 at 00:51
-
@Dev_anon101 I hadn't seen that public key cryptography notation before, but now that I understand it it makes at least a little more sense. How is this better than simply hashing the answer to the secret question? What is `priv_I`? – AndrolGenhald May 12 '18 at 01:08
-
@AndrolGenhald priv is short for private key `priv_I` uses the input `I` as a private key (public key remains the same). It doesn't store the secret answer(database). – Dev_anon101 May 12 '18 at 02:11