Exploiting server side parameter pollution in a query string

Description

To solve the lab, log in as the administrator and delete carlos.

Approach

After accessing the lab, I enabled the FoxyProxy extension to proxy all my requests through Burp Suite. Two requests got my attention: one fetching a JavaScript file and the other a POST request to /forgot-password.

Starting with the GET /static/js/forgotPassword.js, there is an interesting part in the JavaScript script:

forgotPwdReady(() => {
    const queryString = window.location.search;
    const urlParams = new URLSearchParams(queryString);
    const resetToken = urlParams.get('reset-token');
    if (resetToken)
    {
        window.location.href = `/forgot-password?reset_token=${resetToken}`;
    }

This part is responsible for getting the value of reset_token and verifying it. If it exists, it redirects with a GET request to /forgot-password with that reset_token.

From this information, I can build an attack path to get the administrator's reset_token, reset their password, log in as them, and delete the user Carlos.

I started working on how to get the reset_token of the administrator. I went to the POST /forgot-password request and sent it to the repeater in Burp Suite to start working on it.

POST /forgot-password HTTP/2
Host: 0ad9005904e93da6830b064c00c100e6.web-security-academy.net
Cookie: session=XX4y2Xd8qFXhlYM0Idm6QkEykmDJKSrs
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0
...

csrf=lUkBK6PRsgjJbI2kT8jKumH5v93cmXHK&username=administrator

First, I tested for server-side parameter pollution by trying to truncate the query string using the # character and URL encoding it.

I received an error:

Since I truncated the query, there was still a parameter that didn't get its value, and the error indicated it was the field parameter. So I tried adding it to see what I would get:

I received an error indicating an invalid field:

Referring back to my earlier findings about the reset_token, I tried passing it to see if it could be reached:

I received the token in the response:

By simply sending a GET /forgot-password?reset_token=100oji58dtnwesl7euzmeri075etmhwd, I could access the password reset page for the administrator. I right-clicked the response, clicked Show response in browser, copied the URL, and pasted it into my browser. I reset the administrator's password, logged in as him, and deleted the user Carlos, solving the lab.