Credentials include a Claim and a Proof (possibly many).
The Claim is what states one or more facts about your identity.
A Username is one example of a Claim. So is Group Membership, Age, Eye Colour, Operating System, Installed Software, etc…
The Proof is what allows someone to reliably trust the Claim is true.
A Password is one example of a Proof. So is a Signature, a Passport, etc…
Claims are generally public, or at least non-secret, and if not unique, are at least specific (e.g. membership of the group “Brown eyes” isn’t open to people with blue eyes).
Proofs are generally secret, and may be shared, but such sharing should not be discoverable except by brute force. (Which is why we salt passwords).
Password resets can occur for a number of reasons – you’ve forgotten your password, or the password change functionality is more cumbersome than the password reset, or the owner of the account has changed (is that allowable?) – but the basic principle is that an account needs a new password, and there needs to be a way to achieve that without knowledge of the existing password.
Let’s talk as if it’s a forgotten password.
So we have a Claim – we want to assert that we possess an identity – but we have to prove this without using the primary Proof.
Which means we have to know of a secondary Proof. There are common ways to do this – alternate ID, issued by someone you trust (like a government authority, etc). It’s important in the days of parody accounts, or simply shared names (is that Bob Smith, his son, Bob Smith, or his unrelated neighbour, Bob Smith?) that you have associated this alternate ID with the account using the primary Proof, or as a part of the process of setting up the account with the primary Proof. Otherwise, you’re open to account takeover by people who share the same name as their target.
And you can legally change your name.
Pretty much every public web site relies on the use of email for password reset, and uses that email address to provide a secondary Proof.
It’s not enough to know the email address – that’s unique and public, and so it matches the properties of a Claim, not a Proof, of identity.
We have to prove that we own the email address.
It’s not enough to send email FROM the email address – email is known to be easily forged, and so there’s no actual proof embodied in being able to send an email.
That leaves the server with the prospect of sending something TO the email address, and the recipient having proved that they received it.
You could send a code-word, and then have the recipient give you the code-word back. A shared secret, if you like.
And if you want to do that without adding another page to the already-too-large security area of the site, you look for the first place that allows you to provide your Claim and Proof, and you find the logon page.
By reusing the logon page, you’re going to say that code-word is a new password.
[This is not to say that email is the only, or even the best, way to reset passwords. In an enterprise, you have more reliable proofs of identity than an email provider outside of your control. You know people who should be able to tell you with some surety that a particular person is who they claim to be. Another common secondary identification is the use of Security Questions. See my upcoming article, “Security Questions are Bullshit” for why this is a bad idea.]
Well, yes and no. No, actually. Pretty much definitely no, it’s not your new password.
Let’s imagine what can go wrong. If I don’t know your password, but I can guess your username (because it’s not secret), I can claim to be you wanting to reset your password. That not only creates opportunity for me to fill your mailbox with code-words, but it also prevents you from logging on while the code-words are your new password. A self-inflicted denial of service.
So your old password should continue working, and if you never use the code-word, because you’re busy ignoring and deleting the emails that come in, it should keep working for you.
I’ve frequently encountered situations in my own life where I’ve forgotten my password, gone through the reset process, and it’s only while typing in the new password, and being told what restrictions there are on characters allowed in the new password, that I remember what my password was, and I go back to using that one.
In a very real sense, the code-word sent to you is NOT your new password, it’s a code-word that indicates you’ve gone the password reset route, and should be given the opportunity to set a new password.
Try not to think of it as your “temporary password”, it’s a special flag in the logon process, just like a “duress password”. It doesn’t replace your actual password.
Shared secrets are fantastic, useful, and often necessary – TLS uses them to encrypt data, after the initial certificate exchange.
But the trouble with shared secrets is, you can’t really trust that the other party is going to keep them secret very long. So you have to expire them pretty quickly.
The same is true of your password reset code-word.
In most cases, a user will forget their password, click the reset link, wait for an email, and then immediately follow the password reset process.
Users are slow, in computing terms, and email systems aren’t always directly linked and always-connected. But I see no reason why the most usual automated password reset process should allow the code-word to continue working after an hour.
[If the process requires a manual step, you have to count that in, especially if the manual step is something like “contact a manager for approval”, because managers aren’t generally 24/7 workers, the code-word is going to need to last much longer. But start your discussion with an hour as the base-point, and make people fight for why it’ll take longer to follow the password reset process.]
You can absolutely supply a URL in the email that will take the user to the right page to enter the code-word. But you can’t carry the code-word in the URL.
Why? Check out these presentations from this year’s Black Hat and DefCon, showing the use of a malicious WPAD server on a local – or remote – network whose purpose is to trap and save URLs, EVEN HTTPS URLs, and their query strings.
Every URL you send in an email is an HTTP or HTTPS GET, meaning all the parameters are in the URL or in the query string portion of the URL.
This means the code-word can be sniffed and usurped if it’s in the URL. And the username is already assumed to be known, since it’s a non-secret. [Just because it’s assumed to be known, don’t give the attacker an even break – your message should simply say “you requested a password reset on an account at our website” – a valid request will come from someone who knows which account at your website they chose to request.]
So, don’t put the code-word in the URL that you send in the email.
DON’T LOG THE PASSWORD
I have to say that, because otherwise people do that, as obviously wrong as it may seem.
But log the fact that you’ve changed a password for that user, along with when you did it, and what information you have about where the user reset their password from.
Multiple users resetting their password from the same IP address – that’s a bad sign.
The same user resetting their password multiple times – that’s a bad sign.
Multiple expired code-words – that’s a bad sign.
Some of the bad things being signaled include failures in your own design – for instance, multiple expired code-words could mean that your password reset function has stopped working and needs checking. You have code to measure how many abandoned shopping carts you have, so include code that measures how many abandoned password reset attempts you have.
Did I miss something, or get something wrong? Let me know by posting a comment!