For every developer, implementing a password reset feature is a very interesting part. This is where he develops a logic and then implements it in the code. There is no well-defined industry standard on how to implement a secure password reset functionality in your application. So, the result is that every application has a different way of doing the same, starting from emails, unique URLs, temporary passwords, security questions, OTP etc.
Because every developer has a different (in a way) method of implementing such feature, every time the hacker has to think of a newer way to hack. At TO THE NEW Digital, we audit numerous applications with such feature. In this series of blogs, I will analyse common implementations of the password reset functionality in web applications.
We are talking about the applications, which authenticate users with username/email and password combinations. Let’s list the most commonly used ways to implement the password reset feature:
• Email sent with a unique URL to reset the password
• Email sent with a temporary password or current password
• Secret questions asked and then given the option to reset the password
• Use of OTP (One-time passwords) or multi-factor authentication
In this first part of the series, we will look into the first method of implementing this feature. Subsequently we will analyse each of these and will recommend the best practice.
Password reset with unique URL sent over email
This is the most common method of the password reset. The steps involved are below:
• User visits forgot password page and submit the email address/username
• The application generates a URL with a unique token and sends to the registered email address of that account
• User logs in to the email account and clicks the URL in forgot password email
• Now, the user is redirected to a page where he is asked to choose a new password for the account
In all this, there are multiple things that need to be validated at the server end; failing which will lead to a vulnerability in the application. Let me present a case to you. Think of an application that gives the same option of resetting the password. Below screenshot shows an automated email received.
Now when the user click’s this link, he gets redirected to the password reset page of the application. This page gives the option to choose a new password.
Now, when the user fills the new password and clicks Change button, a request like the one shown below is sent.
The catch is to capture this request, and change the value of “email” to a different one and send the request. Doing that might change the password for a different email account if the application does not validate the token and account combination.
So, let’s see what all hacks can be possible in such a case:
1. Changing the email address in the final request
• This is happening because the application does not validate the email address and random token combination to be valid. Before completing the request, the application should check if the token is generated for associated email address only or not.
2. Using the same URL for multiple times
• This might be possible if the application does not ensure that the URL expires after use. If an attacker gets access to such an email once, it can be used to hack an account any number of times.
3. Generating the URL token
• The randomness of the URL token should be very good, else an attacker might use several such URLs and can predict the randomness. For example, the below password reset URL looks fine at first, but let’s see the magic.
But let’s look deeper, this is basically a combination of the email address of the user and date … Base64 encoded twice and then the ASCII Hex.
4. Executing password resets for numerous accounts.
• Though this may seem to be a less severe issue, but if your password reset page does not imply any restriction on the number of requests that can be sent from a device/IP/account, then an attacker may start an automated script and will send numerous requests for password reset.
5. Username enumeration.
• What does the application say, if someone enters an email/username which does not exist in the database? Many applications respond with a response like; “Username is not in the database, please make sure you entered the correct email address/username” or a similar message. But the catch is that this tells an attacker if the email account is registered with the application or not. This will lead to username enumeration.
One more interesting issue can be due to Host header validation. If the application generates the reset password link by taking the Host header value in the request, then modifying the same will result in a forged reset link generation. For example; if the request is modified to change the Host header, as below:
This will send a crafted password reset email to victim account (firstname.lastname@example.org) from the application server. Though this issue is very specific to certain type of application, but this can be used as a phishing attempt. The email will look like:
So finally let me list down some of the recommendations if you are using the above method.
• The application should validate the random token and email associated combination before executing the request
• The password reset URL should have expiry time and can only be used once
• Always ask the user to provide some data before sending an automated password reset email The data can be something like username and date of birth combination
• Implement restriction to avoid automated requests through programs. This can be done by implementing human checks, like captcha
• Implement restriction on the number of requests that can be generated from and IP/device/account within a period of time
Thus, it is important to assess the level of security of your application at regular intervals. This is as simple as answering a 5-minute questionnaire like the one below –