Forgotten password

The easiest avenue into a site

I’ve been writing an email web application recently and I have been thinking about making the forgotten password feature more secure as it is often the easiest avenue for an attacker to get into your web site. The major issue with these features is information disclosure, for example if you have an email account as the username for your web site, the attacker simply enters random email addresses to see which ones are valid accounts depending on the responses from your web site.

So you have to be very careful with the error messages you display and only give the smallest amount of information you can. I see many web sites on the internet display more than they should, if you enter an invalid username or password some web sites are very specific with the error message e.g. “Invalid username” or “invalid username and password”, over the years I’ve learnt when developing my applications to be careful with this information, my error messages will often say “Invalid username or password”, it sounds insignificant but it can make a real difference in improving your overall security of your web site as these little items tend to add up.

How to increase security of a forgotten password feature

This isn’t easy because it is a balance of ease of use and security, getting them both spot on is a real challenge. I decided to abandon the use of an email to login to my application and instead provide a username. When requesting a password reset, a username and email combination is required before the email confirmation will be sent. This reduces the risk mentioned earlier where an attacker can see which accounts are valid by guessing the email address, as they now require two pieces of information.

Once they have entered their username and email combination the site would then check if that combination exists in the table. If the username or email doesn’t exist the site would display a generic error message “Email could not be sent please check your username or email and try again”, thus providing enough information for the user but not giving away too much.

When they enter the correct username and email; an email is then generated with a secure one-time hash that will expire. The hash is a long sequence of characters with a salt [1], which is stored in the table for that user. When clicking on the link the user is presented with a confirmation page that requests the username and email again to provide protection against brute force attacks against the hash. Once the hash, username and email have been confirmed the site can then reset the password.

If you use MD5 in PHP and find that the url is too long, a good tip is to simply follow the process above for creating and checking the hash but then use substr() function in PHP to reduce the length of your hash. So you take a standard hash “098f6bcd4621d373cade4e832627b4f6” and reduce it, the code below takes the hash and starts at position 5 and takes 5 characters from that to produce our unique string with only 5 characters. You can then choose which position to start from and how many characters you would like, just make sure the number of characters you request doesn’t exceed the length of the hash.


$start = 5;
$length = 5;
echo substr("098f6bcd4621d373cade4e832627b4f6", $start, $length);

[1] http://en.wikipedia.org/wiki/Salted_hash

6 Responses to “Forgotten password”

  1. Jan Schneider writes:

    Actually I consider the infamous “invalid username and password” error message a usability nightmare. We are keeping dozens of user names and password with us, and every now and then I can’t login on a rarely used account. This error message doesn’t help me at all. I want to know if it was my user name that I didn’t remember correctly or if I didn’t pick the correct password of my common set.

  2. Gareth Heyes writes:

    I agree it is a usability problem and what I said in the article “This isn’t easy because it is a balance of ease of use and security, getting them both spot on is a real challenge.” is exactly what we are taking about.

    Any suggestions on how we can achieve this goal?

  3. shapcy writes:

    “This isn’t easy because it is a balance of ease of use and security, getting them both spot on is a real challenge.”

    This explains the our problem clearly. It is a balance problem. We should choose the best strategy for our application: more usability,more security or more balanced system.

    I translated this little article to Turkish and published in my blog.

    Forgetten Password – In Turkish

    Regards,
    Mustafa Şapçılı

  4. patmoore writes:

    So now you are going to make someone remember both a username and a password?

    There are going to be 3 possible outcomes to this depending on how valuable the site in question is:

    1) fewer people will register (and/or return) because they will not remember their username/password combination.

    2) You will need a method to have someone be told what their username is given their email address.

    3) People will just start writing the username/password on pieces of paper that others will pick up and can use.

    Rather than do this — think about the idea of a password hint that the user is allowed to create.

    Also consider this if the attacker has access to the email account that the reset password link was sent to. The victim has lots of other issues as well.

    I guess bottomline I think you are taking the security question in the wrong direction. (unless of course you are working for a bank)

  5. Gareth Heyes writes:

    @shapcy
    Thanks for the translation 🙂

    @patmoore
    A password hint is a bad idea because it gives the attacker information that they shouldn’t have. I decided to use the username and email combination but you don’t have to…my goal was to point out the security and usability balance and let you decide for yourself how far you want to take it.

  6. Anonymous writes:

    How secure is any of the above anyway?
    When sending hashes/passwords through email, which is totally insecure as email is sent in plain text and thus can be sniffed.