Cracking a “Fortress” OAuth redirect_uri: A Deep Technical Dive

The article dissects a custom OAuth implementation in a major automotive company's identity system, explains why the redirect_uri is the critical attack surface, and details how systematic fuzzing and a double‑encoding payload ultimately bypass the strict URL validation to hijack user accounts.

Black & White Path
Black & White Path
Black & White Path
Cracking a “Fortress” OAuth redirect_uri: A Deep Technical Dive

SSO and OAuth Quick Start

Single Sign‑On (SSO) lets a user log in once and access multiple services; Google’s ecosystem (Gmail, YouTube, Cloud) is a classic example. Implementations vary – some rely on SAML or third‑party OAuth providers, while large enterprises often build custom SSO systems, which tend to have higher error rates.

OAuth Login Flow

Application (e.g., YouTube) redirects the user to the identity provider (e.g., Google) with parameters such as client_id, redirect_uri, scope, and state.

User authenticates at the provider.

Provider returns an authorization code (or token) to the supplied redirect_uri.

Application exchanges the code for a session cookie, token, or similar credential.

The security boundary lies in the redirect_uri. If an attacker can control its destination, they can capture the authorization code and take over the victim’s account, which is why providers validate redirect_uri strictly.

Two Redirect Types

Exchange Endpoint : Server‑side handling of the code with a 301/302 redirect; the only manipulable vector is redirect_uri.

Dispatcher Endpoint : Client‑side JavaScript processes the response; additional vectors such as state, postMessage, and Unicode differences in window.location can be exploited.

The dispatcher mode offers a broader attack surface; the author previously earned a $12,000 bounty on a similar Google product.

Target OAuth Flow

The target is a global automotive leader with a unified OAuth system driven by a self‑built identity provider. A typical authorization request looks like:

https://idp-connect.company.com/auth/api/v2/user/authorize
?client_id=dummy
&redirect_uri=https%3A%2F%2Fwww.company.com%2Fapi%2Fbin%2Fopenid%2Flogin
&state=[BASE64_STATE]
&scope=openid+profile+email+phone
&response_type=code
&ui_locales=en

After authentication the provider redirects to:

https://www.company.com/api/bin/openid/login?code=AUTHORIZATION_CODE&state=...

This is the exchange endpoint; the state parameter is a simple Base64‑encoded URL and cannot be abused.

Attack Surface Analysis

Application : www.company.com Provider : idp-connect.company.com Exchange Endpoint : https://www.company.com/api/bin/openid/login No Dispatcher Endpoint : clean 301 redirects.

state cannot be abused.

Thus the only viable path is to manipulate redirect_uri. The provider accepts sub‑domains (e.g., abc.company.com), so the challenge is to bypass its strict validation.

Fuzzing the URL Parser

Initial attempts fuzzed single characters ( ) in various URL positions, all rejected. The author then tried two‑character “cluster bomb” payloads, still rejected.

https://a.com%FUZZ%FUZZ.company.com/api/bin/openid/login
https://www.company.com%FUZZ%FUZZ/api/bin/openid/login
https://a.com%FUZZ%FUZZ/api/bin/openid/login

Nothing succeeded, prompting a shift to double‑encoding attacks.

Double‑Encode Attack Vector

When the server decodes redirect_uri once during validation but a later redirect routine decodes it again, specially crafted double‑encoded characters can slip through. The payload used:

https://a.com%2523%40www.company.com/api/bin/openid/login

Breakdown: %2523 → first decode → %23 → second decode →

#
%40

@

Payload Mechanics

Step 1 – Server Validation : The server decodes once, turning the URL into https://a.com%[email protected]/api/bin/openid/login. The validator sees %23 (i.e., #) followed by @www.company.com. In URL parsing, @ separates credentials from the host, so the host is recognized as www.company.com, and the validation passes.

Step 2 – Pre‑Redirect Decoding : Before issuing the 301 redirect, another function decodes %23 again, yielding #. The final redirect URL becomes:

https://a.com#@www.company.com/api/bin/openid/login?code=AUTH_CODE

In the browser, everything after # becomes the fragment identifier. The browser navigates to https://a.com, and the attacker’s page can read the fragment via location.hash, extracting the authorization code. https://a.com/?code=AUTH_CODE&state=... The code is now in the attacker’s possession.

Root Cause Analysis

The server validates redirect_uri after a single URL decode – standard behavior.

Just before the redirect, another function performs an additional decode.

Double‑encoded characters (e.g., %2523 for #) survive the first check but are transformed by the second decode, altering the URL’s semantics and bypassing the validation.

This is not a trivial bug; the redirect_uri check is robust, but the mismatch between validation decoding and redirect‑time decoding creates a hidden exploit path.

The case demonstrates that “fully secure” does not mean “unbreakable” – deeper analysis can still uncover critical flaws.

Original article: https://blog.voorivex.team/story-of-abusing-a-fully-secured-redirect-uri-in-an-oauth-flow
OAuthsecurity analysisauthentication vulnerabilitydouble encodingredirect_uriURL fuzzing
Black & White Path
Written by

Black & White Path

We are the beacon of the cyber world, a stepping stone on the road to security.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.