π οΈ Password reset β
Theory β
Websites that manage user accounts usually have a "forgot password" or "reset password" feature. This offers attackers an interesting vector as it could potentially lead to Account Takeover (ATO).
Practice β
When this feature is present on a website, there a a few things to check.
- Is there a captcha, rate-limit or any other anti-DoS mitigation?
- Is there any kind of validation, from the user, that the password must be reset? This could lead to a kind of DoS on user accounts if there isn't.
- Is the feature relying on security questions that could be easily answered from OSINT or Social Engineering?
- Is the previous password sent in clear-text to the user, indicating that the passwords are not stored in a hashed format?
- If a one-time password (OTP) is sent to proceed with the password reset, is it sent on a secure channel (e.g. mitigating MitM)?
- Can the feature be used by attackers to enumerate users (e.g. error message when trying to proceed with a user that doesn't exist)?
- Is there a password reset link sent? If so:
- Is it still valid after a reset?
- Does it have an expiry date? If so, is it still valid after that period of time?
- Is the link fully random or is there any guessable format that can be reproduced to takeover other accounts?
- Is "password reset" link sent to an email indicated in a parameter that is not correctly filtered? --> Paramater manipulation
///// WIP below
Password Reset Poisoning β
To provide the user with a link to reset its password, some implementations use the result of input headers such as the Host
header. This helps in constructing a resetting password link by keeping the origin (example.com
). By manually changing the Host
header and using a malicious origin (malicious.com
), the user is redirected to malicious.com when clicking the link.
This vulnerability is easy to test.
- Send a request to a forget password mechanism using your own email.
- Change the Host header between the requests
- Check the resetting password link you received via email. If the value of the
Host
header is reflected in the origin in the link (https://www.malicious.com/reset-link.php?token=$TOKEN_VALUE
, then it's vulnerable
Token leak via Referer header β
The Referer
header contains information about the previous web page from which a request has been made. It example1.com
has a link pointing to example2.com
, when clicking on that link, the Referer
header will be set to example1.com
. The Referer
header will print out the whole URL, containing query parameters and so on, not just the origin.
Using the Referrer-Policy
with the directive no-referrer
mitigates the issue.
To test for token leakage:
- The forgot password mechanism has to be used with a valid email address.
- After clicking on the reset password link (received by email), the password shouldn't be changed.
- Upon clicking on the reset password link, it's important to click on another link from another origin.
- By intercepting the request, one can check if the
Referer
header (if set), contains the token.
In a real-world situation, the "other" origin should be vulnerable for an attacker to intercept the token (from the Referer
header).
Paramater manipulation β
When clicking on a reset password button, a request can be sent with a parameter such as email=$EMAIL
. By modifying this parameter, multiple tests can be done to take over the account requesting a reset password.
Based on CyPH3R's blog post:
email=victim@email.com&email=attacker@email.com
email=victim@email.com%20email=attacker@email.com
email=victim@email.com|email=attacker@email.com
email="victim@mail.tld%0a%0dcc:attacker@mail.tld"
email="victim@mail.tld%0a%0dbcc:attacker@mail.tld"
email="victim@mail.tld",email="attacker@mail.tld"
{"email":["victim@mail.tld","atracker@mail.tld"]}
The same can be done when the request uses an API:
("form": {"email":"victim@email.tld","password":"12345678"})