Verbose Error Messages - Security Series #5
Let's talk about error messages. Error messages are GREAT! Well... let me rephrase that, verbose error messages that really let you know what the problem is so that you can correct it and move on are great, right?
For example, look at this error message:
Your entry was not a properly formatted URL, please try again, ensuring you begin with an http:// or https://.
Pretty good, huh? Really let's the user know what was wrong, and how to, maybe, fix it.Now look at this one:
The username you entered was not valid. Please reenter and try again.
Pretty good message, let's the user know what they did wrong so they can fix it. That's a good practice, right?
Nope.
What you've done here is let your hacker know whether or not they have hit on a correct username or not.
I mentioned in a previous post, and I will mention again, and again, and again. The username is HALF of the
authentication. There is no need to let the end user know if they go the right username or not. Most users will
remember their username, and for those that don't, you can have an "I forgot my username" link for them that will
email it to the email address that is on file. All you need is a simple error message that states something along
the lines of:
Incorrect username or password, please try again.
When it comes to security, verbose error message can be bad. Not only are you giving your users and your administrators extra information, you are also giving it to your hackers. Error messages should ALWAYS give the bare minimum amount of informtion to make it (generally) clear what is wrong and what to do to fix it.






- the exact html (including spaces) of your reply. If you have more whitespace in one case and less in the other, it is fairly trivial for a script to make the difference between the two.
- even the response time may provide a hint, if it happens to differ noticeably enough, which could be the case in a robust password storage scheme (salt+slow and strong hashing algorithm), because in this case you would typically first query for the username, then hash the password with the salt contained in the user record only if the username happens to exist. Thus, a slower response might hint to the fact that the username was indeed correct. If necessary the attacker could issue a same request multiple times to discard false positives by observing a statistical difference from the average response time. To make his life that little bit harder, you actually should perform a hash of the user-supplied password with an imaginary salt even if the username was not found.
Otherwise, I don't quite understand how you could possibly test for a password if the username doesn't exist... unless you query for the password, which would imply that you store the password in clear text or that you don't use a separate salt value for each user, which would be a worse practice still.