2
votes

I'm developing an web application using Django.

Currently I am working on sending "reset password link" thorough email (amazon simple email service - SES)

The mechanism I used, is the same with the answer of "simeonwillbanks" below link

Secure ways to reset password or to give old password

  1. Give users a reset password option.
  2. This option saves a unique token for a user. The token eventually expires (hours, day or days).
  3. A link is emailed to the user which includes the token.
  4. User clicks on the emailed link.
  5. If the token exists and isn't expired, the link loads a new password form. If not, don't load the new password form.
  6. Once the user sets a new password, delete the token and send the user a confirmation email.

What I worry about this, I am not sure this way is safe in terms of security. What if the email is captured by a hacker?

I tested on several major websites how they care this.

  1. get an "reset password" email and copy the link.
  2. give the link to other and see if he can change password on my account.

From this test, I figured out that somebody else also can change my password only with the link.

If I cannot do anything on the link, is there way to make email more secure? like as the mechanism of ssl(https) on website?

Thanks!

1
The only thing you can do is send the email using SMTP/S instead of plain SMTP, and keep the expiry period of the token as short as possible (minutes instead of hours or days), but you're right, this commonly used reset password flow is inherently insecure.Robby Cornelissen
You can first of all ask for some additional security details when the token is entered or use a second factor like Text messages/Mobile Numbers. You can also not ask for the email but a login which is never shown to anybody on the site (i.e. if you want to attack somebody you cannot reset his account with the email address alone). All of those adds a small additional layer but also increases support requests (forgotten username etc).eckes
Thanks for the answer guys! @ Robby Cornelissen, Could you explain little more about SMTP/S? I tried to research about it, there was not enough reference.kyle
also I am using boto (python library for aws) for ses, according to their document, Amazon SES sends messages over a TLS-protected connection (TLS version 1.0 only) by default. This method, called opportunistic TLS, means that when Amazon SES establishes an SMTP connection with a receiving mail server, Amazon SES upgrades the connection using the STARTTLS protocol if the receiving mail server supports TLS. If the receiving server does not advertise STARTTLS or if TLS negotiation fails, the connection proceeds in plaintext TLS is not secure enough?kyle

1 Answers

2
votes

It's somewhat secure, though is toast if the user's email was compromised.

I prefer using an HMAC in the URL, which avoids storing tokens in the DB.

If you include the user's IP address in the URL, and in the HMAC, you can be sure the reset link click came from the same computer (router actually) that requested the reset, and that it can't be shared.

Instead of the IP, you could set a device cookie with the username/email and an HMAC, and then check this when the reset link comes in from the email.

The system should ask the user the answer to a secret question after he clicks the link. Even better, send an SMS to his mobile with a short random code and ask for that. This is called https://en.wikipedia.org/wiki/Multi-factor_authentication

Then show the change password form (over HTTPS of course).

While we're here, you should display the same "success" message whether or not the user has an account, to avoid user enumeration attacks.

Also, use a localhost MTA relay or asynchronous email so that a hacker can't tell whether you sent an email (a slow response would indicate that a user exists).