11

On a website I run I have implemented this procedure for account recovery (forgotten password procedure). I would like to know whether there are any issues with it that I have not spotted, that make it insecure.

When the user creates an account, they are required to enter a password (of course) and an email address. They are also required to select a "secret question" from a list of about 20 questions, and enter a "secret answer" to that question. The password and secret question answer are each hashed, each with a different, random salt. Assume that the hashing function used is adequate. (The user can change their email, password and/or secret question/answer at any time, must enter password to do so. I do not impose any password strength requirement, except for a minimum-length requirement.)

If the user needs to recover the account, they go to the account recovery page and enter their user name. An email is sent to the email address associated to their account. This email contains a link which contains a randomly-generated code (site.com/accountrecovery?user=1234&code=bryvthery6y65htee or the like). When the user clicks the link, they are taken back to the site, and assuming the code checks out they are taken to a page where they are asked their secret question and must answer it and at the same time, enter a new password.

Whenever the stored password or secret answer is changed, by whatever method, a new random salt is generated for it.

Are there any issues with this setup that come to mind? I would like constructive criticism. The thinking behind it is that in order to be able to reset the password, the user must have access to the registered email address and must know the secret answer.

Hammerite
  • 213
  • 1
  • 5
  • 1
    Does the user have an option to create their own secret question? – Iszi Jun 13 '11 at 13:05
  • No. ~~~~~~~~~~~ – Hammerite Jun 13 '11 at 13:09
  • 2
    @Hammerite - Might you consider adding one? This is a particular peeve of mine, for "security question" based recovery systems. – Iszi Jun 13 '11 at 13:18
  • 1
    If the secret question is hashed, how is it displayed back to the user? – AviD Jun 13 '11 at 16:53
  • Typo. The secret answer is hashed. The secret question is not hashed. – Hammerite Jun 13 '11 at 17:21
  • @Hammerite - Though this will add complexity to the system, I'd suggest the questions get encrypted also. Certainly, this would have to be via a mechanism that allows the system to decrypt the question, but they should still not be kept in the clear. If someone steals the challenge/response database, cleartext questions are *much* easier to Google. – Iszi Jun 13 '11 at 18:48
  • ...to be more specific, the question should be stored in a way that it is uniquely hashed/encrypted for each user regardless of selection. So, if Bob and Alice both select "What is your mother's maiden name?" *(shudder)*, an attacker looking at the database should neither be able to determine what the question is nor that the two are the same. – Iszi Jun 13 '11 at 18:50
  • @iszi - and how are the questions decrypted to be sent to the user - costly manual intervention? So you need to encrypt it, not hash it. And an attacker that could get the DB would also in many situations be able to get the decryption key also. Lots of complexity there for how much benefit? – nealmcb Jun 13 '11 at 23:06
  • @Iszi the downside to letting users create their own secret questions, is that they will usually create very *bad* ones. "Color?", "one and one?" and "last name" are common. – AviD Jun 14 '11 at 01:26
  • 4
    @Hammerite, is there a reason the userid must be in the link? No reason to expose that... especially if it's his email address. – AviD Jun 14 '11 at 01:30
  • 1
    Possible duplicate: http://security.stackexchange.com/questions/1918/can-anyone-provide-references-for-implementing-web-application-self-password-rese . In any event, @Hammerite this link should be interesting for you. – AviD Jun 14 '11 at 01:34
  • @AviD - The upside to giving users the *option* of creating their own secret questions is that they have the opportunity to create obscure challenge-response combinations. Such as Question="River" Answer="Wyrm". (This is a realm where "security by obscurity" is actually a good thing.) While few users may appropriately take advantage of this, it certainly beats being locked into a set of options that are commonly public record or peer knowledge. – Iszi Jun 14 '11 at 05:38
  • 1
    @Iszi I agree on that part, and I would definitely prefer it *for me* - but most (normal) users would not come up with something obscure enough, would typically find something *very* simple, and then **reuse** that same question in all sites (which is a very large part of the risk, as that is the same as sharing passwords between sites). As I said, its part of a very unclear tradeoff. – AviD Jun 14 '11 at 06:55
  • @AviD: It is necessary to somehow identify which user is visiting the link. One way to do this is by searching a database table for the code, and identifying the user from the row that is returned. But that is probably a bad idea. The other way to do it is by including some identifying information in the url. Of course, this could be (say) the email address, rather than the user id number. – Hammerite Jun 14 '11 at 11:09
  • 2
    @Hammerite, dont forget that the URL gets exposed and stored in many places: history, cache, proxy, etc. Any private information (such as email address) should not be there to be exposed. Even an internal userid is extraneous, since you have to look up the reset code anyway, you gain nothing from including the userid in the url, and you expose additional sensitive information for the potential attacker. As such, it is more recommended that the reset link contain only the reset code, and you look up the user from the code in database. – AviD Jun 14 '11 at 11:16
  • 1
    @Hammerite, I'm inclined to agree with @AviD. I'd say, just send a reset code (one that is totally random, and long enough to be unique). The server, upon reset of that code, can search a database table to identify which user it is for. You say this is a bad idea, but don't say why. It feels slightly safer to me, as it avoids leaking unnecessary information. I don't know whether it's a really big deal, but I'd agree with @AviD. – D.W. Jun 16 '11 at 17:40

2 Answers2

8

As usual - depends on the nature of what you're protecting. Seems decent enough for basic information. May need more if you are writing code for something high end - like web banking.

Whenever secret questions/answers are used, the answer ends up taking the place of a password somewhere, and its easy for that to be your weakest link. Since secret answers can easily be things that an attacker could find out by Googling the person, they can be a real risk factor - and it's hard to tread the line of questions that are so unusual that they are not relatively easy to figure out and questions that are so esoteric or non-applicable that the account owner can't answer them.

I like @Iszi's idea of letting the person write their own Q&A set - that circumvents the problem nicely.

In the case you mention if an attacker can intercept email coming from you system, then they don't need the user's account. That means that the biggest line of defense is that shared secret.

You didn't say, but I'm assuming that all account set up and password reset happens with SSL/TLS protection, right? If not, that would probably be the bigger problem.

bethlakshmi
  • 11,606
  • 1
  • 27
  • 58
8

Overall, this seems reasonable for an average site. I would suggest a few minor changes:

  • Personally, I would consider removing the secret question. I don't think security questions add much security; but they are another secret that the user can forget or get wrong, so security questions have a real cost to the user experience. There has been academic research suggesting that the answers to secret questions have low entropy, and that they can be phished about as easily as passwords can. Therefore, I think removing the secret question will improve usability, and will not have much effect on security. In effect, the security of the system becomes reliant upon the user's email address. The primary risk that the secret question addresses is one where the user closes their email account, and then someone else registers the same email and is able to guess the user's username; or where the user's email account is hijacked; or where the user shares his/her email account with other people.

  • I would add a password strength indicator to the page where the user chooses their password. See what sites like Google use, where there is a bar that dynamically indicates the strength of the password, and that changes colors (red = Poor, yellow = Borderline, green = Good). This might induce/help users to choose better passwords. You probably don't need to impose minimum strength requirements -- this may provide enough of a nudge.

  • I would make the recovery code time-limited, so that it must be used within (say) an hour or two, and then is no longer accepted after the end of the validity period. Also, the link should expire immediately on first use (thank you, @AviD, for pointing this out).

  • Use SSL/TLS (i.e., HTTPS) for all activity related to choosing/setting/submitting the user's password. This will protect against password eavesdropping for users who are accessing your site over an open wireless network; however, it does not protect against Firesheep. Consider adopting SSL/TLS sitewide, which will protect against Firesheep.

(I am assuming you don't have any particularly sensitive security needs: e.g., this is not for online banking or the like.)

D.W.
  • 98,420
  • 30
  • 267
  • 572
  • 1
    @DW - Regarding removal of the security question: If I'm understanding your proposal correctly, the suggestion here actually makes the password reset process *less* secure. For your system, the password reset function is entirely compromised if the user's e-mail account gets hijacked. In Hammerite's system, a password reset requires both control of the registered e-mail *and* knowledge of the security challenge/response. Perhaps the latter is low-entropy, but it still effectively makes the difference between single-factor and two-factor authentication. – Iszi Jun 13 '11 at 18:45
  • @iszi What is "two-factor" about a security question? – nealmcb Jun 13 '11 at 23:09
  • @nealmcb I dont think @Iszi meant "two factor", I think he just meant "two pieces" of authentication. Wrt removing the secret question, I think its a trade-off - it does add a little bit of protection, though that is a very little bit. It comes at the expense of managing it, and user dexperience. – AviD Jun 14 '11 at 01:24
  • +1, this is a very good answer. **EXCEPT** for the part about captcha... I hate captchas, and not just because they're annoying and pointless, I despise captcha from a security point of view. If you want to prevent spamming (which is a very good idea and should be a must, not a "consider") - just prevent it. E.g. limit one reset password email per user an hour, a day, or while the previous one is valid. Whatever makes sense, just enforce that. – AviD Jun 14 '11 at 01:28
  • 3
    @D.W. another point, the links should expire immediately on use. – AviD Jun 14 '11 at 01:30
  • @nealmcb - I mean "two factor" in the sense that an e-mail address could (arguably) be considered as "something you have". Though, since the gateway to that e-mail is (usually) only a password, it's still technically single-factor. – Iszi Jun 14 '11 at 05:34
  • @Iszi not to mention that, since SMTP is *such* and insecure protocol, you don't actually need access to the email to read those emails... – AviD Jun 14 '11 at 06:57
  • 2
    @iszi Yes - this would be single-factor. There is already enough odd and confusing interpretations of the term "two-factor" without adding this to them mix. – nealmcb Jun 14 '11 at 18:29
  • @AviD, good points. Thank you. As far as CAPTCHAs, a second reason to use them on the reset page is to prevent an attacker from using the reset page to guess at usernames and learn which usernames are valid. Do you have any thoughts on alternative ways to defend against that threat? – D.W. Jun 16 '11 at 17:38
  • 1
    @D.W. - re guessing usernames - sure, just present the same output page (after requesting a reset) no matter what. He'd only know if the username was valid, if he had access / monitored the account's email - in which case, he probably already knows it's valid (I can think of a couple of *very* narrow scenarios that that is not the case, but in general...). How would CAPTCHA prevent that? – AviD Jun 16 '11 at 21:56
  • 1
    @AviD, Oh, you are right. That's an oversight on my part. Your solution is better. I've removed the CAPTCHA recommendation. – D.W. Jun 17 '11 at 04:16
  • 2
    Yay! One more evil CAPTCHA has been eradicated! Cheers for effective security mechanisms! I'd +1 you again just for that, but I cant vote twice... – AviD Jun 17 '11 at 07:28
  • 2
    Here is some research showing security questions to be less effective against phishing: http://www.truststc.org/pubs/498.html – Van Gale Jun 17 '11 at 22:13