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.

  • 1
    Does the user have an option to create their own secret question?
    – Iszi
    Jun 13, 2011 at 13:05
  • 2
    @Hammerite - Might you consider adding one? This is a particular peeve of mine, for "security question" based recovery systems.
    – Iszi
    Jun 13, 2011 at 13:18
  • 1
    If the secret question is hashed, how is it displayed back to the user?
    – AviD
    Jun 13, 2011 at 16:53
  • 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, 2011 at 1:30
  • 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, 2011 at 11:16

2 Answers 2


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.)

  • 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, 2011 at 18:45
  • 3
    @D.W. another point, the links should expire immediately on use.
    – AviD
    Jun 14, 2011 at 1:30
  • 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, 2011 at 18:29
  • 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, 2011 at 7:28
  • 2
    Here is some research showing security questions to be less effective against phishing: truststc.org/pubs/498.html
    – Van Gale
    Jun 17, 2011 at 22:13

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .