
All you ever wanted to know about building a secure password reset (NSFW) - ColinWright
http://www.troyhunt.com/2012/05/everything-you-ever-wanted-to-know.html?HN2
======
patio11
This happened to be posted literally, to the minute, while I was ripping out
some of the advice from my codebase, so let me take exception with one
recommendation:

If someone attempts a password reset on foo@example.com, and there is no
record in the DB for foo@example.com, immediately tell them so.

Why?

1) While this does "leak" the fact of foo@example.com not being in the DB
(and, by consequence, can be used to verify whether any email is in the DB),
naive implementations of the best practice will _also_ leak that via a side
channel. If you would not immediately greenlight $20k to have a security
consultant spend one week auditing this feature extensively to avoid the
timing attack, a) your app is _not important enough_ for this level of
security and b) this buys you no real security, just the illusion of it.

1.5) This is totally security theatre if you have a registration process which
checks for provided emails already being the in the DB, for example for
telling people "That email is taken." Different route through the maze but
same cheese at the end.

2) You can already spearphish people for their accounts on example.org . Start
with an email list of people. Spearphish for their accounts irrespective of
whether they have them or not. Collect wins since losses cost your botnet
nothing at the margin.

3) MOST IMPORTANTLY: you're buying yourself six years of frustrated emails
from customers which had _90% totally automatically discoverable solutions_ if
you do this the "right" way. I'm speaking from experience. Many of your
customers have multiple emails they habitually use. If you do the best
practice, every time they misremember which one they signed up with, you get a
support email. _This will be your #1 cause of support emails and the cost for
dealing with them is astronomically higher than the minimal marginal gain in
security for your users._

Edit: Omnibus response for people doubting that a side channel attack is
possible:

The attacker wins with microsecond precision over the open Internet and
nanosecond precision over the local network, which is plausibly achievable on
all of the cloud providers than HNers like to host their apps at. Microsecond
precision is enough to discriminate between "record in DB" and "record not in
DB" on many plausible application architectures, even if your HTML/headers
returned are exactly identical for the two cases (and they frequently won't be
out of the box).

For example, the relevant code for Bingo Card Creator includes the line

user = User.find_by_username(params[:email])

This line takes approximately 30x longer to execute if it finds a user in the
DB versus not finding a user. Why? ActiveRecord. You could, if you had a mind
to, trivially discriminate between the two cases in under a week over the open
Internet. If you _really_ wanted to ruin my day, you could get a prepaid Visa
card and get a VPS from Rackspace on the same intranet, then discriminate
between the two responses in under an hour, again without tripping anything.

Some folks think there are trivial ways to defeat timing attacks. You are
either mistaken or you have a very different view of the word "trivial" than I
do.

~~~
efsavage
Not showing "user not found" errors may not be a strong security measure, but
it's an effective and important privacy measure.

And while you may think that the fact that your app isn't a risk because it
doesn't deal with sensitive issues, your users may not agree.

~~~
pornel
If the site has a registration form, then hiding e-mail in password reset is
pointless.

Site's registration form validation will give the same information and without
side-effects.

~~~
Xylakant
That's false for well designed signup forms. Signup forms should never leak
"email/username does not exist" but only "this combination of email/username
and password is unknown". This prevents the trivial attack. Timing attacks
might still be possible, but then at least you're on the same level for both
attack vectors.

~~~
mootothemax
_Signup forms should never leak "email/username does not exist" but only "this
combination of email/username and password is unknown"._

Can you explain this to me? Is the only difference the error message used, or
are you suggesting that apps should support multiple accounts with the same
email/username but with different passwords? Or something else entirely? :)

Personally, I don't understand what difference a message makes; it'd be
trivial for a user to test by signing up for an account themselves. And not
having a unique login identifier would be a nightmare. Which makes me think
I'm missing something obvious (damn this headcold, it makes me feel so much
more stupid than usual!).

~~~
Xylakant
I'm sorry, my mistake here. I was thinking login forms. But the same thing can
be done with signup forms, as explained in the response to the comment
following yours.

------
jgrahamc
The inclusion of the large graphic taken from a pornographic web site is not
necessary (he could just write a single paragraph describing the potential to
discover subscribers of porn sites) and shows poor judgement by the writer.

~~~
gizmo686
The style of the article was showing screenshot examples of relevant sites.
That may or may not be the most productive use of screen space, however the
porn screenshot fits in with the other ones.

Just to be clear, I think the inclusion of screen shots is an excellent use of
screen space.

~~~
jtheory
Screenshots are useful. But it would have been trivial to _keep a technical
article SFW_.

As-is, this is a solid article that I can't send to my team because of that
one poor choice.

Here's why:

1) I don't know the personal histories of everyone I work with, and it's none
of my business (they aren't expected to tell me).

2) Some people would be seriously distressed to have their boss or co-worker
email them anything with remotely sexual content.

3) I can't reliably identify who these people are, and so I simply shouldn't
send anything with sexual content to co-workers/employees.

Doesn't this same logic apply to just about everyone?

------
ColinWright
I don't usually do this, but I am genuinely curious about this happening. At
about 10:31 BST this morning the following item was submitted (not by me):

<http://news.ycombinator.com/item?id=4280213>

It quickly gained an additional 5 upvotes, and I was looking forward to the HN
community's discussion, because I am about to revamp a certain site, and was
looking to see what people thought about the specifics listed on that page.

It got to number 7 on the front page at about 11:10. Then it disappeared. It's
now down between 900 and 950 or so. Yes, I went and checked.

I was disappointed - I always look forward to in-depth and/or illuminating
discussions on HN - but more than that, I'm _really_ curious to know why this
item has been flagged so heavily, or, alternatively, buried by the
moderators/admins.

So please, here it is again. You're (obviously) free to flag it again if you
feel the need, but please, let me know why.

Thanks.

 _Added in edit: If you upvote this submission then you should probably go
upvote grn's original:<http://news.ycombinator.com/item?id=4280213> ._

~~~
yread
I didn't flag it, but I remember reading about it some time ago. Probably here
<http://news.ycombinator.com/item?id=4005239>

------
patio11
P.S. This article is a) very good even if I disagree with the advice and b)
NSFW due to an unfortunately chosen example using a large image sourced from a
pornographic site.

------
tptacek
His flowchart is missing an edge, between "user changes their password for any
other reason other than password reset" and "password resets corresponding to
that user are deleted from storage".

It's a minor detail, but an easy one to get right.

~~~
ColinWright
Something like this?

<http://www.solipsys.co.uk/images/PasswordResetFlow.png>

I agree that there's more going on, but this is beyond the original remit. The
flowchart can be made seriously more complex by adding in the flow for the
simple changing of a password, which needs similar attention to details.

Would you care to assist in producing such a chart? I have provide the DOT
source for this image if you like.

------
16s
Can the porn picture be removed so people who want to keep their jobs can read
it? Really, most of us keep-up with HN from work and would violate work-place
policy by reading this article due to the choice of picture.

~~~
Xylakant
Actually, I'm a bit curious (and even though it's off topic) and since I'm
from europe I'd love this to get a peek into american workplace ethics:

Why is this NSFW? The picture does not show nude girls, actually the level of
nudity is about what I can get to see in a public pool or on the street on a
hot day. The picture certainly is suggestive and hints at something more. The
article does not link to a porn site, load images from a porn site or even
discuss a porn site. Is the hint that porn sites (or this specific porn site)
exists sufficient for the NSFW marker?

I'm asking since this is certainly not considered NSFW for anyone I know - I
can see "worse" in respectable TV documentaries which air in the regular
evening programme. And I guess there's little chance of minors being around
here either.

~~~
mootothemax
I'm also from Europe, and find it shows a poor sense of judgement, mostly
because the image is not necessary to prove the points being made.

The other problem I have is, as you say, the image _is_ suggestive. Imagine
someone at your office glancing at your monitor whilst walking past. Would
they bat an eyelid? I can't think of many workplaces outside of the porn
industry where your professionalism wouldn't be called into question, however
briefly.

~~~
Xylakant
Actually, yes. I'd be absolutely unconcerned to have the picture on my screen
since it's obviously a screen cap in some article. In some work places I
worked I'd be more concerned about coworkers/clients seing me reading a blog
on paid time instead of coding than about that screencap.

~~~
mootothemax
_Actually, yes. I'd be absolutely unconcerned to have the picture on my screen
since it's obviously a screen cap in some article._

Wow, that's interesting _and_ surprising; where are you based, and what types
of companies have you been working for?

I'm definitely haven't worked in lots of cultures, but have worked in offices
in the UK, Poland, Belgium and Germany, for major companies and for small, and
in each one of them, Questions Would Be Asked were I to have that image on my
screen, and in most cases - but admittedly not all - my professionalism would
be called into question.

 _In some work places I worked I'd be more concerned about coworkers/clients
seing me reading a blog on paid time instead of coding than about that
screencap._

Hehe, well that's a very different argument, and one that you and I agree on
:)

~~~
Xylakant
I'm currently berlin based, but worked all around germany from bavaria in
munich, stuttgart, karlsruhe and cologne. I worked for all kinds of companies
that revolve around web stuff, been the tech lead of a top 25 ranked web-
development shop and had anything from tiny via government jobs to enterprise-
class customers. However, I didn't do short-term jobs with changing coworkers,
so I guess it's a bit about how well you know your coworkers and how much
trust you have in them. It might draw a tongue-in-cheek kind of remark, but
not a serious question of my professional abilities.

I'm more curious about the fact that people could obviously be afraid that
this might be a firing offense - and I can't think of a single place where
this could be possibly used to construct a case.

------
sltkr
Even if the password-rest-page doesn't leak information about which e-mail
addresses have accounts associated with them, the register-new-account-page
usually does. Of course websites could work around this by sending an e-mail
message to the address to confirm ownership first, but this is rarely done in
practice.

An easier fix is for users to randomize the email-addresses they use. For
example, if you have a Google Mail account, you can receive messages at
username+randomdata@gmail.com; if you use different random data for each site,
nobody will able to probe for your account as described in the article, even
on poorly-designed websites.

The advantage of this approach is that it's something that privacy-minded
users can do themselves, without having to rely on website developers to get
things right.

------
ColinWright
As requested, marked NSFW. It will be interesting to see if the mods change it
back, or to something else.

~~~
AUmrysh
is it NSFW because of graphic or nude images, or because of language?

~~~
user24
screenshot of porn site with nudes.

~~~
ColinWright
Er, except they're not nude. Suggestive, yes, but not nude.

~~~
user24
I was in my garden, the sun was on the screen. Looked more-or-less nude from
where I sat.

------
3amOpsGuy
Really good article, well written. Easy to read.

>> Everything i believe is important

In the spirit of completeness, you could expand the details of this paragraph:

>> What we want to do is create a unique token which can be sent in an email

There should also be a Time to Live on the token, and it should only be usable
once. On the landing page for the link, the user needs to enter* their email
address to avoid someone arriving at the url from a means other than the
original email.

I feel like i should give an example there, let's say the attacker figured out
your random id generation method, say it's a hash of a timestamp for
simplicity, if they generate a few thousand links for around 6pm, they may get
lucky).

* They don't actually need to enter it, UX guys would be having minor heart attacks at that suggestion, but they could choose their email address from a small table of plausible looking but made-up addresses, or something to that effect, e.g. Bank of America uses a photograph the user setup beforehand.

~~~
papsosouid
Rather than force people to do an extra step, why not just use a secure method
of generating reset IDs?

------
sophacles
I'm late to this party, but one thing I take minor issue with in this article,
is the "log everything" section. I agree that logging is good, and don't want
to give a wrong impression on that, but, logging _everything_ can have some
problems. Users regularly clicko the username/password fields and you'll get
exploitable logs of: odd username from IP followed shortly by real user name
from same ip with successful log-in. If you don't secure your logs well, you
now have a potential security breach, and those log systems can be vulnerable
to all the stuff you went through that password securing rigamorole to avoid
(bad software, sql injection, etc, etc.) I bring it up, because a lot of times
people don't think to secure the logging system as much as the other stuff,
partly because it is regularly behind the dmz, and partly because it is just
off the standard security map for user security issues.

Just $.02 for this conversation :)

------
woodchuck64
> Bottom line: treat secret answers as secret!

Bottom line: never give real answers to secret questions! I can change my
password, I can change my credit card if it's compromised, I can even change
my social security number if need be, but I can't change the name of my first
pet or where I first met my spouse. Never give real answers to secret
questions.

------
ajanuary
The one thing I've seen mentioned before that wasn't in here is to delete the
reset token if the user successfully logs in.

------
ColinWright
As expected, this submission has been flagged.

As expected, no one has said _why_ it's been flagged.

Unexpected bonus, the original submission has gained enough points to be back
on the front page despite having been flagged off it. So that's a win.

 _Added in edit: Now it's been flagged off again. There are times I really
don't like the dynamic on HN._

~~~
ximeng
I've seen this happening on a couple of accasions with stories that are
uncomfortable for HN. E.g. see <http://news.ycombinator.com/item?id=4160121>

It might be interesting for one of the sites that scrape HN to reverse
engineer the decay factor for different type of stories and find out which
stories are "disappeared" quicker.

------
gleb
Don't store reset tokens in database, PITA and not scalable. Instead HMAC sign
reset URL, using Rails' MessageVerifier class for example.

The reset URL should also expire in about a day, so include and sign timestamp
as well.

And the way we know this is good advice is that most large sites do it this
way already.

~~~
trapexit
You'll also want to implement some defense against short-term replay attacks
(i.e. before the token expires).

You could include a sequence number in the token, but this, of course,
involves a database write, which is what you were trying to avoid in the first
place.

A better approach would be to store in the database the time that the user's
password was last changed, and refuse to honor any reset tokens that are
timestamped prior to that time.

~~~
DenisM
Beter yet, mix in a random data field from the user record into the reset link
(have it signed with HMAC), and regenerate the random each time reset it done.
This way no reset link can be used twice, and no db writes are done when reset
link is created.

------
finnw
How about this:

    
    
        if database.contains(email) or md5sum(secretSalt + email).startsWith('4'):
            print "An email has been sent to this address with further instructions"
        else:
            print "Sorry, this address does not exist in our database"
    

Now one in 16 (pseudo-randomly selected) emails will appear to be in the
database, whether or not it is really there.

The attacker will still see the "confirmation" when they enter the victim's
email address, but they cannot know if it was really in the database or if it
was one of those random false positives.

~~~
lvh
Timing attack vulnerability. A negative containment check is probably faster
(at least statistically measurably so) than a positive one, so you'll see
three peaks:

\- contained \- false positive \- not contained

Probably with the first two being close together and the latter two being
close together.

------
sandstrom
TLDR;
[http://lh5.ggpht.com/-ke9GVduXaaY/T7rBCWHFkYI/AAAAAAAADmY/xv...](http://lh5.ggpht.com/-ke9GVduXaaY/T7rBCWHFkYI/AAAAAAAADmY/xvEOczv44Zg/Password-
Reset5.png?imgmax=800)

~~~
user24
There's still a timing attack there, just compare the time it takes for the
server to send the email, instead of the time it takes to return the message.

~~~
jholman
What? How does the attacker know when the server sends mail?

Nice summary, sandstrom. Not as useful as reading the whole article, but much
higher value-per-effort. ;)

~~~
user24
You can leak that data in a number of ways. Trivially, the server might
timestamp the email. Less trivially, you could position yourself on the same
network as the server and just time how long it takes to receive the email
(I'd opt for this technique personally). You might be able to monitor IP IDs
of the mailserver to see when it sends an email (technique:
<http://nmap.org/book/idlescan.html>). The emails themselves might have some
kind of predictable sequence/message ID in the headers so you can cause the
server to send many many emails and watch for the sequence increment. You
could create a custom DNS server for your email domain that causes the email
server to hit your DNS and log when the lookup was made. Probably other
techniques.

edit: Not to mention that this chart _still_ leaks the fact that
joe@example.com is or is not a member of the site in question.

------
shimsham
This is welcome, useful and covers many of the salient points. However,
without wanting to detract from the content, this is 2012. None of these
issues are new. For people who aren't doing some or all of this, isn't it time
to consider not reinventing this well-worn wheel? Libraries of reusable code;
now there's a good idea! Now I know what mom meant when she talked about the
OO silver bullet.

I'm off to invent distributed processing and BSD sockets.

~~~
ColinWright
You have libraries that do all this? Fantastic - please submit a reference so
we can all benefit from it - thanks.

------
stephenr
I have to disagree with this point

    
    
        Despite plenty of guidance to the contrary, the first point is really not where we want to be. The problem with doing this is that it means a persistent password – one you can go back with and use any time
    

If a developer can't work out how to implement a one-use password that forces
a password change after login, they shouldn't be writing code.

~~~
Deregibus
That puts the onus on the user to immediately log in after receiving the
temporary password. Until they do (which could be months later), they have
their password to the site stored in email. The DoS issue that was mentioned
in the next paragraph is also a pretty good reason to use a reset link
instead.

~~~
stephenr
So you're suggesting that a user who goes to a site to login, and can't
(forgotten password) will then completely lose any and all reason to login to
the site, AFTER doing what's required for a new random password to be
generated and sent to them?

Sounds pretty far fetched to me.

------
jimrandomh
While it's not common practice, I strongly believe that for particularly
important services, there should be a time delay built into the reset process,
so that if a user's email account is compromised in such a way that both the
attacker and the victim receive the emails, the victim gets a chance to stop
the reset process before any damage is done.

------
cdawzrd
Please mark this article as NSFW!

~~~
lightweb
Now we know what kind of sites this Microsoft MVP likes to peruse. :-)

------
wheelerwj
i just came to say I am really looking forward to reading this.... when i get
home. why did you post porn in this?

~~~
ColinWright
Just wanted to ask: Are you one of these people who can't distinguish between
the author of a post, and someone who posts a link to it?

~~~
wheelerwj
it was most of a generalized comment on the post than an actual question. I
promise to be more careful next ColinWright.

------
teebot
So I read it at work because it was marked NSFW

~~~
shimsham
National Science Fair at Wisconsin?

