Application takeover via Password Reset Token Theft

Numb Shiva
3 min readJan 18, 2021

When adding a “Password Reset” function to your application you should ensure it has same security considerations as any other critical function within the application. Attackers often spend extra time trying to break these mechanisms to gain some sort of unauthorised access.

There are some key considerations that must take place when implementing this function to ensure it cannot be abused by attackers:

  • it should essentially be impossible for an attacker to obtain in any manner a password reset token for another user
  • tokens must have a limited time span and be invalidated upon use
  • tokens must only be authorised to perform a password reset

Weakness #1 — static reset tokens

Each user in the application had a password reset token created at time of account creation and stored in the application database as part of the credential information. This meant each account had a single reset token valid for the lifetime of the account, independent of how many times the user forgot their password.

As the token was not invalidated after a period of time or once used, this meant that even if the legitimate user reset their password, an attacker still had access to the token and in turn the user’s account, another weakness detailed in weakness two. It also appeared likely that the token could not be invalidated without deleting and re-creating the account.

The token was returned in a ‘200 OK’ response from the API endpoint, so while not visible within the web page itself, was still easily obtainable by an attacker simply using an interception proxy such as Burp Suite. This meant that an attacker could easily write a script to test a list of usernames and obtain the token for each by parsing the resulting response.

Token leaked for enumerated user account

Weakness #2 — incorrect token authorisation checks

The even bigger problem was the token itself had excessive permissions and was able to perform almost any action for which the user already had permissions. For example, the token could be used to update the user’s profile or perform API interaction to access any data for which the user had access to.

These two issues meant that the application was prone to two critical security issues.

Account takeover

An attacker able to obtain a reset token now had the ability to change a user’s email address associated with the account and perform an actual password reset (among other changes).

Stealing the root user’s token

Application takeover

If an attacker targeted an admin account, they could essentially take full control of the application, locking out other administrator accounts and accessing all data within the application. Alternately, they could make changes to any other account of their choice, including escalating privileges of a low privileged account they already had access to.

Escalating privileges using a stolen admin token

These issues can be easily resolved in the following methods. By combining all of these, you take a defence in depth approach with each layer increasing the security of the reset function:

  • ensure reset tokens are only generated once a user runs the “password reset” function
  • tokens must only be provided to the user requesting the reset via an email address previously validated and connected to the account and not returned via the web application front end
  • tokens must only be authorised to perform a reset and not have permissions for any other purpose
  • tokens must not be easily guessed, predictable or able to be brute forced
  • bonus: ensure your application doesn’t accept arbitrary host headers so reset emails can’t be poisoned with attacker controlled links

--

--

Numb Shiva

itsec guy. sometimes i internet. oscp/penetration testing/red team.