June 25, 2026
Lab 4#: Exploiting a mass assignment vulnerability
Hello readers! I am Mohammad Reza, and today we will be discussing how to solve the fourth lab in the PortSwigger API Testing Academy…
By mohamed
2 min read
Hello readers! I am Mohammad Reza, and today we will be discussing how to solve the fourth lab in the PortSwigger API Testing Academy: "Exploiting a mass assignment vulnerability".
Mass Assignment occurs when software frameworks automatically bind incoming HTTP request parameters to backend data models without proper filtering. If developers aren't careful, an attacker can modify sensitive object properties that should never be user-controllable — such as changing privileges, or in our case today, force-applying a 100% discount.
First, log in with wiener:peter, navigate to the store, and add the jacket to your cart. Its price is $1337.00.
If we head over to our shopping cart and attempt to click "Place order", the application instantly rejects the transaction due to insufficient store credit
Let's jump over to Burp Suite and examine the intercepted traffic under the HTTP History tab.
When inspecting how the checkout process operates, you'll find two key API interactions targeting the same endpoint:
- GET /api/checkout
- POST /api/checkout
Here is where the magic happens. Look at the response of the GET request compared to what the client typically sends during a POST request:
As highlighted in the server's GET response leaks a structural hidden object that the user frontend normally omits:
This strongly indicates that the backend model supports a discount parameter on checkout. If the API blindly maps incoming parameters directly into the object model (Mass Assignment), we can inject this block ourselves.
Right-click the POST /api/checkout request and send it to Burp Repeater. Let's manually inject the chosen_discount parameter into our JSON payload:
{
"chosen_discount":{
"percentage":0
},
"chosen_products":[
{
"product_id":"1",
"quantity":1
}
]
}{
"chosen_discount":{
"percentage":0
},
"chosen_products":[
{
"product_id":"1",
"quantity":1
}
]
}When we send this request the API accepts it without throwing any structure or parameter errors.To double-check if our input is actually interacting with backend variables, change the percentage value from 0 to a string like "x". The server immediately fires back an error stating the input isn't a valid integer. This confirms our input is being actively bound and processed by the business logic!
Since the backend accepts integers for the discount percentage, let's change the value from 0 to 100 to see if the system will let us check out for free:
"chosen_discount": {
"percentage": 100
}"chosen_discount": {
"percentage": 100
}Send the modified request in Repeater. As you can see the server returns a sweet 201 Created response and redirects to /cart/order-confirmation?order-confirmed=true.
Lab Solved! 🎉