Mobile App Penetration TestJan Kahmen22 min read

Secure Password Reset Process

How can the password reset process be designed securely? What are the advantages and disadvantages of implementing a reset function?

How can the password reset process be designed securely? What are the advantages and disadvantages of implementing a reset function?

There are numerous perfectly legitimate perspectives on this topic -- but also plenty of poorly defined processes. Most end users will have encountered many of them already. Using a few examples, this article explains how the password reset process should work and what to consider during implementation. It can also serve as a test catalog for a penetration test.

Password Storage: Hashing, Encryption, and Plaintext

First, it is important to clarify how passwords are stored. There are fundamentally three ways passwords can be kept in a database:

  • Plaintext -- Passwords are stored as-is, without any transformation.
  • Encrypted -- Typically symmetric encryption is used, and the encrypted password is stored in a dedicated column.
  • Hashed -- A one-way function where the password is ideally combined with a salt.

Passwords should never be stored in plaintext! A single injection vulnerability, a careless backup, or any one of a dozen other small mistakes -- and every password is publicly exposed.

Encryption is better but still has weaknesses. The problem: wherever data can be encrypted, it can also be decrypted. Once someone manages to convert the encrypted data back to plaintext, the passwords are exposed again.

Hashing is a one-way function. The only way to match a submitted password against the stored hash is to hash the input as well and compare the results. To prevent attacks using tools like rainbow tables, a random value -- the so-called salt -- is added to the process. This forces every password to be tested individually via brute force.

A detailed guide can be found in the article "Passwörter unknackbar speichern" (German).

Always Reset the Password, Never Remind

Why is a "reminder" needed in the first place? Because the user has forgotten their password. But what is the actual goal? To help the user log in again. A password reminder function is the wrong approach for this purpose.

The term "reminder" is used colloquially, but the real objective is to help the user regain access to their account in a secure manner. Since security is paramount, there are two reasons why sending the current password simply does not work:

  • Email is an insecure channel. Just as sensitive data should not be sent over HTTP, the transport layer of email is not secure either. In fact, the problem is even worse than with an insecure transport protocol, because emails are often stored permanently and can be viewed by system administrators.
  • The service operator should not have access to the password anyway. As explained in the previous section on storage, a correct implementation makes it impossible to retrieve the password and send it via email.

Username Enumeration and Its Impact on Anonymity

The message "No user with this email address is registered" is a poor choice. The problem is obvious: a website is indirectly confirming whether or not a user with a particular email address is registered.

The resulting risk is a social engineering risk. Once an attacker can associate a person with a service, they have actionable information. For example, they could contact the person, pose as a representative of the website, and request additional information in a spear-phishing attack.

This practice also introduces the risk of username enumeration: an entire collection of usernames or email addresses can be checked for their existence on the website simply by sending a large number of requests and evaluating the responses. The German Federal Office for Information Security (BSI) also provides recommendations on web application security (German).

Sending a Reset Password vs. a Reset URL

Next, the method of resetting the password must be considered. There are two common approaches:

  • Generate a new password on the server and send it via email
  • Send a unique URL via email through which the reset can be performed

The first approach has another major problem: it makes malicious account lockout trivially easy. If the email address of someone who has an account on the website is known, that account can be locked at any time by resetting the password. This amounts to a denial-of-service attack. Therefore, a reset should only be performed after the account owner has been successfully verified.

A reset URL is a web address that is unique to that specific reset process. This URL must be randomly generated and must not reveal any information about the affected account. For example, a reset URL should not simply be a path like "/reset/?user=Jan".

Instead, a unique token must be created that is sent as part of the reset URL via email and is then matched on the server to a record for the corresponding user account. This confirms that the owner of the email account is indeed the person who wants to reset the password. Since this process allows the user to create a new password, the URL must of course be loaded over HTTPS.

Furthermore, the token should be time-limited so that the reset process must be completed within a specific time window -- for example, one hour. This minimizes the window during which a reset is possible. If someone intercepts the reset URL, they can only use it within this short time frame. An attacker can of course request a new reset at any time, but that will generate a new token and a new URL.

Finally, the reset should be a one-time operation. Once the reset process is complete, the token must be deleted so that the reset URL no longer works. As described in the previous point, this ensures that an attacker has only a very limited window to misuse the reset URL. In addition, the token is no longer needed after a successful reset anyway.

Some of these steps may seem excessive, but they do not impair the usability of the function in any way and they improve IT security -- even if the scenarios they guard against are hopefully rare. In 99% of cases, the user will complete the reset within a very short time and will not need to reset their password again in the foreseeable future.

The Role of CAPTCHA

A CAPTCHA is less of a security measure and more of a means to distinguish between humans and machines. Its purpose is to prevent the automated submission of forms, which could naturally be abused for attacks on IT security. In the context of password resets, a CAPTCHA means that the reset function cannot be exploited automatically -- neither to flood a person with emails nor to check for the existence of accounts (which should not be possible in the first place if the recommendations in the section on identity verification above have been followed).

Secret Questions and Answers

The problem with password resets that rely entirely on email is that the account security of the website in question depends 100% on the security of the email account. Anyone who has access to the email has access to every account that can be reset simply by receiving an email. For such accounts, the email address is essentially the master key to one's digital life.

One way to mitigate this risk is to implement secret questions and answers. The user selects a question whose answer only they should know, and may then be asked to answer it before a password reset is carried out. This provides additional assurance that the person requesting the reset is indeed the account owner.

However, when it comes to secret questions, users need to be protected from themselves.

So what makes a good secret question? There are several factors:

  • Conciseness -- The question must be to the point and unambiguous.
  • Definitive answer -- No question should be used that the same person might answer differently at different times.
  • Diverse answer space -- A question about one's favorite color would yield only a small set of possible answers.
  • Hard to discover -- If the answer is easy for anyone to find out, it offers no protection.
  • Stable over time -- A question about one's favorite movie might have a different answer a year later.

An important aspect of the answer component of secret questions is storage. If the answer is stored in plaintext in the database, it carries risks similar to plaintext password storage: if the database is exposed, the value is immediately visible, potentially compromising not just the affected application but also other entirely unrelated applications that use the same secret questions.

Secret questions and answers also make users more vulnerable to social engineering. Hardly anyone would attempt to directly extract an account password from someone. However, it is entirely possible to casually chat with a person about many aspects of their life that relate to secret questions without raising suspicion. The whole idea behind secret questions is that they refer to personal life experiences and are therefore easy to remember -- and that is precisely the problem: people enjoy talking about their experiences! Little can be done about this, other than ensuring that the available secret questions are chosen so that their answers are less easily obtained through social engineering.

Two-Factor Authentication

So far, the discussion has focused on verifying an identity based on the requester's knowledge. An additional secret constant is considered a factor of authentication. In most scenarios, biometric validation is hardly practical, especially in the area of web application security. Therefore, the focus is typically on the second attribute in two-factor authentication (2FA): possession. A common approach for this second factor is the use of a physical token, such as an RSA SecurID or Google Authenticator. These generate a cryptographic PIN that is only valid for a short time and cannot be derived through static analysis.

Reset via Username Versus Email Address

Should the reset only be possible via the email address? Or also via the username? The problem with resetting via the username is that the user cannot be notified about an invalid username without revealing whether someone else has an account with that name. When resetting via email, as described in the previous section, the legitimate owner of the email address can always receive feedback without the address's existence in the system being made public. With just a username, this is not possible.

The answer is therefore: email only! If resets via username are allowed, there will inevitably be cases where the user is confused about what is happening, or where the existence of accounts is disclosed. While it is only a username and not an email address, and anyone can choose any available username, the widespread reuse of usernames means there is a high probability that account owners will be implicitly revealed.

So what happens if someone forgets their username? Unless the username is already the email address (which is often the case), the process is similar to a password reset: the user enters their email address and receives a message at that address without its existence being revealed. The only difference is that the message contains the username rather than the password reset URL. Alternatively, the email explains that no account exists for this address.

Identity Verification and Email Address Accuracy

A central aspect of password resets is verifying the identity of the person requesting the reset. Is it actually the legitimate account owner? Or someone trying to take over the account or harass the owner?

Email is obviously the most convenient and widely used channel for identity verification. While it is not absolute proof, and there are many cases where simply receiving email at the account holder's address is not sufficient -- especially when a high degree of trust in the identity is required (hence the use of 2FA) -- it is almost always the starting point of a reset process.

The crucial factor is that the email address is actually correct in the first place. If a typo has crept in, the reset will simply never arrive. An email verification process during registration is a reliable way to ensure the address is correct. The workflow is well-known in practice: after registration, an email is sent with a unique URL that must be clicked to confirm that the recipient is indeed the owner of the email account. If login is only enabled after this step is completed, there is a clear incentive to provide the correct email address.

As with many security aspects, this model comes at the cost of usability but offers a higher level of IT security in terms of trust in the user's identity. For websites where the user places great importance on a successful and secure registration and is willing to take an extra step (e.g., paid services or banking), this may not be an issue. For accounts that the user considers "throwaway accounts" -- for example, to comment on a post without providing personal information -- the extra effort could be a deterrent.

Identifying Who Initiated the Reset

There is naturally room for misuse of the password reset function, and malicious actors can exploit it in various ways. A simple but effective technique for verifying the source of a request is to include the requester's IP address in the reset email. This gives the recipient clues to identify where the request originated.

Email Notification About a Change

A theme that runs throughout this entire article is communication: the account owner should be informed as much as possible at every step of the process about what is happening -- without revealing information that could be exploited for malicious purposes.

A password change can occur in two different situations:

Changing the password while logged in because the owner wants to use a new password. Or resetting the password while logged out because the owner has forgotten it. Although this article primarily focuses on resetting, a notification in the first case reduces the risk that someone else changes the password without the legitimate owner's knowledge. How could this happen? A common scenario: someone has obtained the legitimate owner's password (through a reused password compromised elsewhere, a keylogger, or because it was easy to guess) and changes it to lock out the owner. Without an email notification, the actual owner has no knowledge of the change.

In the case of a reset, the owner has of course initiated the process themselves (or has gone through the various identity verification measures described above), so the change should come as no surprise. Nevertheless, the email notification serves as positive feedback and additional reassurance. It also ensures a consistent user experience across both scenarios.

Delegating Responsibility to Other Providers

Building secure account management is not easy in practice. This is not because it is technically particularly difficult, but because there is a multitude of configuration options. It is not just about the reset, but also about the entire registration process, secure password storage, handling of multiple failed login attempts, and much more.

Today, there are numerous third-party providers that take the burden of developing all of this in-house and abstract everything into a managed service. Options include Keycloak, OpenID, OAuth, Google, and Facebook, among others.

Penetration Testing to Find the Weakest Link

All of the points mentioned above are relevant for securing an individual account. However, what must always be considered is the entire ecosystem surrounding the account. These scenarios are always part of a penetration test.

Conclusion

Even though this article may seem extensive, there is still plenty of additional material on this topic. For example, the role of a recovery email address or the question of what happens when access to the email account is lost. As already mentioned, the difficulty with password resets lies not in the technical implementation but in the multitude of possible attack vectors. Comprehensive technical guidelines on "evaluating authentication solutions" (German) can be found at the BSI.

There are numerous examples where faulty implementations have led to problems, and there are many more precedents where failed resets have caused damage.

Caution is therefore advised when designing the reset process. A threat tree for the various touchpoints is helpful, and when building the function, one should think like an attacker -- otherwise there is a high probability that someone other than a commissioned pentester will do exactly that!

Our Services