portswigger-all-labs

Complete PortSwigger Web Security Academy Lab Writeups Detailed, categorized solutions for every lab — from APPRENTICE to EXPERT — covering all 30 vulnerability types.

View on GitHub

Labs Covered

This write-up covers Three PRACTITIONER-level labs from the PortSwigger Web Security Academy related to API exploitation and testing:

2 Exploiting server-side parameter pollution in a query string

This lab demonstrates how manipulating query string parameters can lead to server-side parameter pollution, potentially allowing unauthorized actions or information disclosure.

3 Finding and exploiting an unused API endpoint

This lab shows how attackers can discover and abuse undocumented or unused API endpoints that may expose sensitive functionality or data.

4 Exploiting a mass assignment vulnerability

This lab illustrates how improper handling of object properties in API requests can be exploited through mass assignment, allowing attackers to modify unintended data fields.

LAB 2 - Exploiting server-side parameter pollution in a query string

Lab Description :

image

Overview

Server-side parameter pollution can occur when user-supplied query parameters are reflected into internal API requests. By manipulating query parameters, it’s possible to inject, override, or truncate server-side requests.


Test Scenarios

1. Truncating Query Strings

Use a URL-encoded # (%23) to attempt truncation:

GET /userSearch?name=peter%23foo&back=/home

This may result in:

GET /users/search?name=peter#foo&publicProfile=true

Note: Always URL-encode #. If not encoded, the browser treats it as a fragment and doesn’t send it to the server.

Indicators:

Goal: Bypass conditions like publicProfile=true to access restricted data.


2. Injecting Invalid Parameters

Use URL-encoded & (%26) to inject new parameters:

GET /userSearch?name=peter%26foo=xyz&back=/home

Results in:

GET /users/search?name=peter&foo=xyz&publicProfile=true

Indicators:


3. Injecting Valid Parameters

Inject known valid parameters (e.g., email):

GET /userSearch?name=peter%26email=foo&back=/home

Results in:

GET /users/search?name=peter&email=foo&publicProfile=true

Indicators: Look for changes in behavior indicating the parameter was processed.


4. Overriding Existing Parameters

Inject duplicate parameter names:

GET /userSearch?name=peter%26name=carlos&back=/home

Results in:

GET /users/search?name=peter&name=carlos&publicProfile=true

Backend behavior:

Exploit Potential: Override with privileged usernames (e.g., name=administrator) to escalate access.


Solution :

Visit the My-Account page, click on forgot password. Enter any username & capture the request.

image

The server responds with Invalid username.

Server side parameter pollution -

What if we give value of username as administrator?

This time we get this response which confirms that administrator account exists.

image

Upon adding a # at the end of the username, the server responds differently.

URL encode the special characters else the frontend will not send the entire url to backend.

image

So from this we can understad that there might be a parameter called **Field**

Upon adding &a=b, the server responds differently again - "error": "Parameter is not supported."

image

This is a good indication that the backend server does process the parameter.

Now we can try sending any invalid value to field parameter (**&field=test#**) to check what the server responds.

Hidden parameter in JS file -

The a JS file contains the following code which reveals a hidden parameter called reset_token.

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

Now in the field parameter we can enter this - **&field=reset_token#**.

image

Now having the passord reset token for the administrator user, we can perform a GET request to https://0a5200b30487309981671bc100890068.web-security-academy.net/forgot-password?reset_token=0envuvi6f1vnz0o6m7az4iykrixayq20 url to reset the admin’s password.

We now get a page to set a new password for the admin user.

After resetting, we can login ad administrator.

image

Goto Admin panel & delete the user carlos to solve the lab.

image


LAB 3 - Finding and exploiting an unused API endpoint

Lab Description :

image

Overview

This guide outlines techniques for identifying and interacting with API endpoints during a security assessment or penetration test.


Identifying API Endpoints

Even when API documentation is available, it may be outdated or incomplete. Actively browsing applications that use the API can reveal additional information.


Interacting with API Endpoints

Once endpoints are identified, interact with them using Burp Repeater and Burp Intruder to:


Identifying Supported HTTP Methods

Different API endpoints may support multiple HTTP methods:

Example: Supported methods for /api/tasks

GET /api/tasks        -> Retrieves task list.
POST /api/tasks       -> Creates new task.
DELETE /api/tasks/1   -> Deletes task with ID 1.

Use Burp Intruder’s HTTP verbs list to cycle through potential methods automatically.

Note: When testing HTTP methods, target low-priority objects to minimize unintended consequences.


Identifying Supported Content Types

API endpoints often expect data in a specific format. They may therefore behave differently depending on the content type of the data provided in a request. Changing the content type may enable you to:

To change the content type, modify the Content-Type header, then reformat the request body accordingly.
You can use the Content Type Converter BApp to automatically convert data submitted within requests between XML and JSON.


Solution :

Login as wiener using the provided credentials - wiener:peter

Goto leather jacket and can see the price and our credit

image

Try to buy the leather jacket it says not enough store credit giving

image

Upon adding the leather jacket to cart, the following API request is sent.

image

Let’s now check which HTTP methods are supported by the API by sending an OPTIONS request.

image

From the response we can see that the API responds - **"error":"Only 'application/json' Content-Type is supported"**.

image

So let’s change the content type to application/json using Content-Type Converter extension & send the request.

image

Now the API responds - "error":"'price' parameter missing in body"

So now let’s set the price parameter in the body of the request to 0 & see what happens. And Open below request in orginal session and can see that price has become 0.

image

The request is successful & the price might have changed. Checking the home page confirms that the price of the jacket is now $0.

image

Now we can order the jacket & solve the lab.

image


LAB 4 - Exploiting a mass assignment vulnerability

Lab Description :

image

Overview :

Mass assignment vulnerabilities

Mass assignment (also known as auto-binding) can inadvertently create hidden parameters. It occurs when software frameworks automatically bind request parameters to fields on an internal object. Mass assignment may therefore result in the application supporting parameters that were never intended to be processed by the developer.

Identifying hidden parameters

Since mass assignment creates parameters from object fields, you can often identify these hidden parameters by manually examining objects returned by the API.

For example, consider a PATCH /api/users/ request, which enables users to update their username and email, and includes the following JSON:

{
    "username": "wiener",
    "email": "wiener@example.com",
}

A concurrent GET /api/users/123 request returns the following JSON:

{
    "id": 123,
    "name": "John Doe",
    "email": "john@example.com",
    "isAdmin": "false"
}

This may indicate that the hidden id and isAdmin parameters are bound to the internal user object, alongside the updated username and email parameters.

Testing mass assignment vulnerabilities

To test whether you can modify the enumerated isAdmin parameter value, add it to the PATCH request:

{
    "username": "wiener",
    "email": "wiener@example.com",
    "isAdmin": false,
}

In addition, send a PATCH request with an invalid isAdmin parameter value:

{
    "username": "wiener",
    "email": "wiener@example.com",
    "isAdmin": "foo",
}

If the application behaves differently, this may suggest that the invalid value impacts the query logic, but the valid value doesn’t. This may indicate that the parameter can be successfully updated by the user.

You can then send a PATCH request with the isAdmin parameter value set to true, to try and exploit the vulnerability:

{
    "username": "wiener",
    "email": "wiener@example.com",
    "isAdmin": true,
}

If the isAdmin value in the request is bound to the user object without adequate validation and sanitization, the user wiener may be incorrectly granted admin privileges. To determine whether this is the case, browse the application as wiener to see whether you can access admin functionality.

Solution :

Login as wiener using the provided credentials - wiener:peter

image

The below we can see the price of leather jacket

image

I try to buy the jacket but failed

image

Add the leather jacket to cart. Now while checkout, the broswer sends the following API request.

image

Then I identfied methods supported by api/checkout using OPTIONS

image

So from the Get form above 4 image request we can see the json is send back and post request is supported as we can see in 5 image above, So we will create payload which will submit the 100 discount for product 1,So we can buy it below is the payload

{
 "chosen_discount":{
 "percentage":100
 },
 "chosen_products":[
 {
 "product_id":"1",
 "quantity":1
 }
 ]
} 

As we can see that sending below request gives us created response,Now I open this request in orignal session than lab is solved

image

Now in the checkout page we can see that the discount has been applied successfully & thus the lab is solved.

image