Skip to content
Field Detail
Platform PortSwigger Web Security Academy
Type API Testing
Difficulty Practitioner
Objective Discover and exploit an undocumented PATCH endpoint on the product price API to set the jacket's price to $0 and purchase it

Finding and Exploiting an Unused API Endpoint

I logged in as wiener:peter — $0 balance, jacket costs several hundred dollars.

Screenshot
Screenshot
Screenshot

Adding the jacket to the cart triggered a GET /api/products/1/price in Burp's history. The page source pointed to a JS file:

Screenshot
<script type="text/javascript" src="/resources/js/api/productPrice.js"></script>

Fetching the script revealed a setPrice() function — the front-end was designed to receive price updates from the API. That's not proof the back-end accepts external writes, but it's a strong signal worth testing. Sending OPTIONS to confirm supported methods:

OPTIONS /api/products/1/price HTTP/2
Screenshot
Allow: GET, PATCH

PATCH is listed — the UI only uses GET, but the endpoint accepts partial updates. OPTIONS is the fastest way to discover this: the Allow header lists every method the endpoint accepts, no guessing required.

Testing PATCH:

PATCH /api/products/1/price HTTP/2
Screenshot
{"type":"ClientError","code":400,"error":"Only 'application/json' Content-Type is supported"}

The error message is a recon asset — it told us the exact format required without any guessing. Resending with the correct content type:

PATCH /api/products/1/price HTTP/2
Content-Type: application/json
Content-Length: 11

{"price":0}
{"price":"$0.00"}
Screenshot

Accepted. The cart updated to $0.00. Changing product prices is clearly an admin operation — but the endpoint had no authentication check. Any authenticated user could call PATCH /api/products/1/price. The "unused" means unused by the UI, not absent from the back-end; the attack surface was always there.

Placing the order:

Screenshot
Screenshot

Lab solved :P

Resources