1

The context is a password reset functionality. The user has requested a password reset, either via the web, or via a call to the help desk.

The proposed solution is, behind the scenes:

  • If Self-Service via the web - require the user to prove that they are the account owner by making them answer their security question
  • Set the password to a temporary, randomly generated password
  • On the server, generate an email that contains a link
  • The user clicks the link and is prompted to enter a new password
  • As long as the new password meets complexity requirements, the new password is set.

The question is, there are two options on the table for the link that is sent to the user.

Option 1: a lookup table of random tokens mapped to usernames, with an expiration.

Option 2: Encapsulate the username, temporary password, and expiration time into an encrypted blob, and send that in the email, and avoid the database

I'm concerned that option 2 is less secure. The data may be logged or cached in proxy servers. And even though the blob is encrypted, the fact that it is out there, potentially multiple times, increases the sample set of data available for potentially reverse-engineering the encryption key.

Am I overly concerned? Is it safe to send an encrypted blob of data in a URL like that? Or is that a bad practice? If it is a bad practice, what are the compelling arguments against it?

3 Answers3

0

I don't discuss the security of the password link since I see the problem with your approach even before this link is generated. Your first step after some unauthorized user requested a password reset is to:

Set the password to a temporary, randomly generated password

The problem with this approach is, that a reset of the password of a user can simply be requested by anybody. Based on your description the users password then gets immediately set to some random value, which would immediately deny access to the real user. The user only gets access back if it follows the sent password reset link or triggers their own password reset.

In the mean time an additional step was added to address my concerns:

If Self-Service via the web - require the user to prove that they are the account owner by making them answer their security question

This does not actually prove that they are the account owner. The actual prove for this would be entering the password, which the user no longer has. Answers to security questions instead tend to be easily solvable for others since they a) tend to be simple and b) tend to contain information which can be found on the internet (i.e. Facebook page of user etc). Also, the attacker only needs to know the answer to the security question once in order to reset the password again and again, meaning an effective DoS to the real user.

Also, there is no actual need to reset the password immediately, since the password itself is not known to an attacker. This kind of procedure was only added to make the link simpler, i.e. for technical but not security reasons. But the link can simply contain a username and expiration, signed together with a server side secret. This way the link functions as a time limited request for password change, authorized by the server. The actual changing of the password should only happen once the link was clicked and a new password set by the user.

For more recommendations on this kind of functionality see How to implement “forgot password” functionality?.

Steffen Ullrich
  • 190,458
  • 29
  • 381
  • 434
  • I believe the OP means something along this lines of `urlparam=base64encode( AES( (userid | randompassword | expiration), key) )`, where key is known only to his server. The link is emailed, the user clicks the link, then the script decrypts the urlparam, and resets the password (if before the expiration). If that's the case, I'm hardpressed to see how a malicious actor could reset a password for another user - especially if integrity verification is used in conjunction with encryption (e.g. AES-GCM). Are you seeing an attack vector here that I'm missing? – mti2935 Mar 31 '21 at 18:37
  • @mti2935: Based on my understanding of the description the first thing is to set the users password to some random value, only then mail the link. I don't even analyze the security of the link. My argument is only that an attacker can ask for a password reset and that this immediately changes the password to a random value as proposed. I've changed the answer to better clarify this problem. – Steffen Ullrich Mar 31 '21 at 18:51
  • You are correct in your assessment, and I raised the concern as well. The response is "We will require them to answer their security questions in order to proceed with the password reset." In their mind, that alleviates the "anybody can reset the password" problem. I'll update the original question – John Arrowwood Mar 31 '21 at 21:57
  • @JohnArrowwood: I'm not comfortable with this additional step either, since answers to security questions are very often trivial to find out. I don't any actual need to reset the password immediately in the first place, it would be much safer to only reset it once the link is clicked. And there is no actual need - the link could simply contain username + expiration, signed with a server side secret to protect against manipulations. – Steffen Ullrich Apr 01 '21 at 05:04
0

Simply generate random string to be attached to the link, eg: site.com/reset/3818d8adng and log it into the table and as soon as the user resets the password via the link mark the link as non-active eg(used=1) and even if the link is logged somewhere and if somebody tries to reset the password he will not be able because the link is not valid.

mrSotirow
  • 152
  • 1
  • 3
  • That would be Option 1 – John Arrowwood Mar 31 '21 at 22:01
  • At least this is how I do, I generate the random string and insert it into the table for example password_reset_request and few columns like id,user_id,reset_token,used , and as soon as the user reset the password from the link like: site.com/reset/881jdhjd you set the reset token 881jdhjd to used. – mrSotirow Apr 01 '21 at 15:59
0

I'm concerned that option 2 is less secure. The data may be logged or cached in proxy servers. And even though the blob is encrypted, the fact that it is out there, potentially multiple times, increases the sample set of data available for potentially reverse-engineering the encryption key.

If you are doing the encryption correctly you don't need to be concerned about someone reverse engineering the encryption key based on collected ciphertext.

What you need to be concerned about is (if you use a global key) some ding-dong developer accidentally (or on purpose) disclosing the key. Then those collected ciphertexts can be decrypted to reveal usernames and temporary passwords.

Am I overly concerned? Is it safe to send an encrypted blob of data in a URL like that? Or is that a bad practice? If it is a bad practice, what are the compelling arguments against it?

It's good to be concerned.

It's a bad idea to try and use some scheme that hasn't been thoroughly analyzed. We don't have the time or money to do a reasonably complete analysis for you via this forum.

Therefore, it would likely be best to use a password reset scheme that has already been shown to be reasonably secure. The scheme is going to look more like option 1 than option 2.

hft
  • 4,940
  • 17
  • 32