6

I am implementing a password reset feature for a web application and am contemplating adopting an implementation similar to Django.

In a nutshell, Django creates a token who is comprised of a timestamp and a hash of the timestamp and the User ID. This hash is a HMAC and is used to verify that neither the timestamp or the user ID have been tampered with.

In addition to the timestamp, information about the user such as her password salt are hashed. This way, if the user changes her password, the token will become invalid, reducing the window of opportunity for an attacker.

The source code for the token generator can be viewed here and here is the pseudocode:

function make_token(user)
  timestamp = current timestamp (now)
  value =  timestamp + user.id + user.password
  hash = create_hmac("some secret", value)
  return timestamp + ":" + hash

function check_token(user, token)
  timestamp = token.split(":")[0]
  hash = token.split(":")[1]

  if timestamp is after expiration date
    return false

  value =  timestamp + user.id + user.password
  comparate = create_hmac("some secret", value)

  // if the hash has changed, the token has been tampered with or the user has 
  // changed their password. 
  if hash != comparate
    return false

  return true

This seems like a good solution to me. Websites running Django have been doing this since 2008 or so and I cannot find any reports of a vulnerability.

I did some research and someone on Hacker News did not like this approach. There are also a couple of tickets on the subject that express concern. However, I am yet to find a specific reason as to why this is might be insecure.

Is this a secure approach to generating password reset tokens? If not, why?

3

As with any question of "is X secure" the answer will, to some extent, be "that depends on your exact requirements from a security standpoint, the threats you face, the type of application and the environment that you'll deploy in"

However with that caveat out of the way, I'd say that the scheme outlined above sounds relatively reasonable from a security perspective and is definitely better than a lot of password reset features I've seen in the past.

The bug report you linked descibes a very specific scenario (the attacker has read access to specific sections of the server-side code and configuration, but not other access) which wilst it does represent a risk, is a really marginal one (to me) as if they have that access there's likely other stuff they would attack before they start generating fake password reset links for users.

The comments from the HN thread are more general in nature and don't seem to descibe a specific threat to this scheme beyond Thomas' general disquiet with schemes that avoid the standard approach that he describes in his comment. Whilst his points are reasonable, that's not to say that the Django scheme is broken, more that there are trade-offs involved.

  • I disagree that escalation from "has a dump of your production DB with hashed passwords" to "reset any user's password and log in" is marginal (it appears the reference to settings.py has now been removed). – Flash Nov 22 '17 at 1:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.