Friday, April 25, 2014

Implementing Forgot Password with Email

It turns out that application developers sometimes need to implement a forgot password feature but don't have much identity data about the users in the system.  Neither can they always be so flexible as to require users to establish personal security questions.  These things are a key part of my forgot password security recommendations.  But the reality is that sometimes you don't have any information about a user except their username and email address.  Heck, sometimes email address IS the username.

In this type of situation, implementing a secure forgot password feature is challenging.  Sending a password reset link via email is probably the best option (barring a non-automated solution where users call customer support).  So here I will offer up some specific ideas on how to secure the process when using email.

  1. When a user invokes the forgot password process, don't say anything about whether the username entered was recognized or not.  It should simply display a generic message such as: "Thank you. If the username you provided is valid, we will send you an email with instructions on how to reset your password".
  2. Along with the above, don't show the email address where the email was sent.  It might give legitimate users a warm, fuzzy feeling but it definitely helps attackers in a number of scenarios.
  3. The password reset link in the email message should incorporate a GUID or similar high-entropy token. The token could be a parameter in the query string or part of the URL path itself.  It doesn't really matter.
  4. Allow only one valid token per user at any given time.
  5. Make sure the email message does not include the username.
  6. Make sure the link can be used only once.  In other words, invalidate the token immediately when an HTTP request containing that token is received.
  7. The link should expire.  Depending on your situation, implement logic to invalidate the token 10, 20, or 30 minutes after the email is sent out.  Make it a configurable value so it can be adjusted if needed without a code change.
  8. The password reset page (the one that appears after clicking the link) should force the user to re-enter his username.
  9. If the username entered is incorrect 3 times in a row, lock the account.  Remember, your application knows which username is associated with the token.  The person attempting to reset the password should know it as well.
  10. After a successful password reset, send a confirmation email to the user to notify them it happened.  This can alert users to fraud if they didn't initiate it.
  11. Throughout each step of the process, make sure the application is logging everything that occurs so there's a solid audit trail in case something goes haywire.
So those are the mitigating controls I came up with.  Feel free to let me know in the comments if you have any other ideas!

(updated on May 5, 2014 based on some feedback I received)

Wednesday, April 16, 2014

Autocomplete="off" Now in Disfavor

In case you missed it, both IE 11 and Chrome recently made a change and they now ignore autocomplete="off" on password input fields within HTML pages.  This attribute is something I've always recommended for input fields that contain sensitive data so that browsers won't store the data locally where it could be compromised.  Apparently the changes were made solely because lots of people are using password managers.  Here's a snippet from a messy MSDN blog post that tries to explain the reason for changing IE:
Password Managers improve real-world security, and the IE team felt it was important to put users in control. Users rely on their password manager to permit them to comfortably use strong passwords. Password managers encourage strong, unique password creation per site, but unique, strong passwords are often difficult to remember and type on touch devices. If the browser doesn't offer to autocomplete a password, the user assumes that the browser is broken. The user will then either use another browser that ignores the attribute, or install a password manager plugin that ignores it.
I'm not sure I agree.  Moving to another browser would not have worked since they all honored the attribute until recently.  It is also stated plainly that users could use a password manager plugin to overcome the restriction.

And here's a snippet from a message posted by the Chrome team with their reasoning:
We believe that the current respect for autocomplete='off' for passwords is, in fact, harming the security of users by making browser password managers significantly less useful than they should be, thus discouraging their adoption, making it difficult for users to generate, store, and use more complex or (preferably) random passwords.
Maybe I don't understand the decisions because I don't use a password manager.  Either way, it is good that all browsers continue to honor autocomplete="off" for non-password inputs (type="text") so that sensitive data such as credit card numbers can be protected.