API — The Order Number That Wasn't Yours
Category: API · Difficulty: Easy
Scenario
shop.kashsec-labs.test has a mobile app backend at /api/v2/. You placed one order (order #5510) and, out of curiosity, opened your browser's DevTools to watch the app's network traffic while checking your order status.
Provided data
The request your app made when you opened "My Order":
GET /api/v2/orders/5510 HTTP/1.1
Host: shop.kashsec-labs.test
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjo0NDIxfQ.redacted
And the response:
{
"order_id": 5510,
"user_id": 4421,
"item": "KashSec hoodie (M)",
"shipping_address": "412 Birchwood Ln, Apt 3",
"payment_last4": "4242"
}
Curious what a neighboring order number returns, you replay the exact same request with only the URL's number changed:
GET /api/v2/orders/5509 HTTP/1.1
Host: shop.kashsec-labs.test
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjo0NDIxfQ.redacted
Your task
Find the flag hidden in whatever /api/v2/orders/5509 actually returns.
Hint 1
Your `Authorization` header proves *who you are* — it doesn't automatically mean the server checks whether the specific order you're asking for actually belongs to you.Hint 2
This is the exact same underlying flaw from this section's earlier IDOR challenge — just wearing an API's clothing instead of a classic web app's. The OWASP API Top 10 has a name for it: it's the #1 item on that list.Show full answer
The API accepts a valid, authenticated request and then fetches whatever order ID appears in the URL — without ever checking thatorder_id 5509's owner matches the user_id encoded in your bearer token. Requesting /api/v2/orders/5509 returns: {"order_id": 5509, "user_id": 4420, "item": "Server rack cooling fan", "shipping_address": "KASHSEC{bol4_1s_th3_new_1dor}", "payment_last4": "8810"} — someone else's full order, including their address, with the flag planted directly in the address field. This is BOLA (Broken Object Level Authorization), the API Security path's #1 risk: your token proves identity, but the server never separately verified authorization for this specific object.The flag
KASHSEC{bol4_1s_th3_new_1dor}
Why this matters beyond the CTF
BOLA is, by a wide margin, the most commonly found and most damaging API vulnerability class in real bug bounty programs and pentests — precisely because, like classic IDOR, it requires nothing more than two accounts and a willingness to change a number. Path 21's BOLA & BFLA lesson (and the matching BOLA/BFLA Playground lab) cover the full methodology: this challenge is the compressed, self-contained version of exactly that technique, applied to a JSON API instead of a rendered web page.
Bonus round — a second, subtler variant
The same app has a DELETE endpoint for cancelling your own pending orders:
DELETE /api/v2/orders/5510 HTTP/1.1
Host: shop.kashsec-labs.test
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjo0NDIxfQ.redacted
Hint
You already confirmed GET on 5509 returns someone else's order with no ownership check. Does that necessarily mean DELETE has the exact same bug, or could the server check ownership on writes but not reads (or vice versa)?Show answer
In a genuinely well-tested app, you can't know without actually trying — and that's the point of this bonus round. In this scenario, the same missing check applies toDELETE too: the endpoint only verifies the token is valid, not that the token's user owns the specific order being deleted, meaning any authenticated user could cancel any other user's pending order. This is why a real BOLA assessment tests every HTTP method on every object-referencing endpoint separately, rather than assuming a fix (or a bug) on one verb automatically applies to the others.The entire technique demonstrated here — capture a legitimate request, replay it with a different object ID, see what comes back — is literally the entire BOLA-hunting methodology used in real assessments. It doesn't get more complicated than this; it just gets applied more exhaustively, across every endpoint and every HTTP method.