Luke a Pro

Luke Sun

Developer & Marketer

🇺🇦
EN||

Open Redirect Vulnerability

| , 5 minutes reading.

1. Definition

An Open Redirect vulnerability occurs when a web application accepts a user-controlled parameter and uses it to redirect users to an external URL without proper validation.

While open redirects may seem low-severity on their own, they are highly valuable to attackers because they abuse the trust users place in legitimate domains. A phishing link using trusted-bank.com/redirect?url=evil.com appears more legitimate than a direct link to evil.com.

2. Technical Explanation

Many legitimate applications need redirect functionality:

  • Post-login redirects: Return users to their original page after authentication
  • Marketing tracking: Redirect through tracking systems before reaching destinations
  • Single Sign-On: Redirect between identity providers and applications

Vulnerable Pattern:

https://example.com/login?redirect=https://evil.com

After successful login, the application redirects to evil.com without validation.

Common Vulnerable Parameters:

  • redirect, redirect_uri, return, returnUrl
  • next, url, target, destination
  • continue, goto, out, redir

Bypass Techniques: Attackers bypass weak validation using various tricks:

# Basic
?redirect=https://evil.com

# Protocol-relative
?redirect=//evil.com

# Domain confusion
?redirect=https://example.com.evil.com
?redirect=https://example.com@evil.com
?redirect=https://evil.com/example.com

# URL encoding
?redirect=https%3A%2F%2Fevil.com

# Parameter pollution
?redirect=https://example.com&redirect=https://evil.com

3. Attack Flow

sequenceDiagram
    participant Victim
    participant Attacker
    participant TrustedSite as Trusted Site
    participant PhishingSite as Phishing Site

    Attacker->>Victim: Sends phishing email with link<br/>trusted-bank.com/redirect?url=evil.com

    Note over Victim: Link appears legitimate<br/>Domain is trusted-bank.com

    Victim->>TrustedSite: Clicks link to trusted-bank.com

    TrustedSite->>TrustedSite: Processes redirect parameter

    TrustedSite-->>Victim: 302 Redirect to evil.com

    Victim->>PhishingSite: Browser follows redirect

    Note over PhishingSite: Fake login page<br/>identical to trusted-bank.com

    Victim->>PhishingSite: Enters credentials

    PhishingSite->>Attacker: Credentials captured

4. Real-World Case Study: Google OAuth Open Redirect (2016)

Target: Google OAuth 2.0 authentication flow. Vulnerability Class: Open Redirect in OAuth callback.

The Vulnerability: In 2016, researcher Egor Homakov discovered that Google’s OAuth implementation had an open redirect vulnerability in the redirect_uri parameter validation.

The Attack:

  1. OAuth requires applications to register allowed redirect_uri values.
  2. Google’s validation was too permissive for certain registered domains.
  3. An attacker could find a legitimate application with an open redirect on its own domain.
  4. Chain: Google OAuth -> Legitimate App (with open redirect) -> Attacker site.

Attack Chain Example:

1. User clicks: accounts.google.com/oauth?redirect_uri=legitimate-app.com
2. Google validates: legitimate-app.com is registered - OK
3. Google redirects to: legitimate-app.com/callback?code=AUTH_CODE
4. legitimate-app.com has open redirect: /goto?url=evil.com
5. Attacker receives: evil.com?code=AUTH_CODE
6. Attacker exchanges code for access token

Impact: This allowed attackers to steal OAuth tokens by chaining vulnerabilities. Google strengthened their redirect_uri validation and encouraged stricter matching patterns.

5. Detailed Defense Strategies

A. Allowlist Validation

Only allow redirects to pre-approved destinations.

const ALLOWED_DOMAINS = [
  'example.com',
  'subdomain.example.com',
  'partner-site.com'
];

function validateRedirect(url) {
  try {
    const parsed = new URL(url);
    return ALLOWED_DOMAINS.includes(parsed.hostname);
  } catch {
    return false;
  }
}

B. Relative URL Only

Restrict redirects to relative paths (same-origin only).

function safeRedirect(url) {
  // Only allow paths starting with /
  if (url.startsWith('/') && !url.startsWith('//')) {
    return url;
  }
  return '/'; // Default safe redirect
}

Warning: Be careful with protocol-relative URLs (//evil.com).

C. Indirect Reference Maps

Use tokens instead of direct URLs.

const REDIRECT_MAP = {
  'dashboard': '/user/dashboard',
  'settings': '/user/settings',
  'logout': '/auth/logout'
};

// Usage: /redirect?target=dashboard
function handleRedirect(target) {
  const destination = REDIRECT_MAP[target];
  if (destination) {
    return redirect(destination);
  }
  return redirect('/');
}

D. User Confirmation

For external redirects, show a warning page.

<div class="redirect-warning">
  <h2>You are leaving example.com</h2>
  <p>You are being redirected to an external site:</p>
  <p><strong>https://external-site.com</strong></p>
  <p>We are not responsible for the content of external sites.</p>
  <a href="https://external-site.com">Continue</a>
  <a href="/">Go back to example.com</a>
</div>

E. Strict OAuth Configuration

For OAuth implementations:

  • Exact Match: Require exact redirect_uri matching, not prefix matching.
  • No Wildcards: Avoid wildcard patterns in registered redirect URIs.
  • HTTPS Only: Only allow HTTPS redirect URIs in production.
# Good: Exact match only
Registered: https://app.example.com/oauth/callback
Valid:      https://app.example.com/oauth/callback
Invalid:    https://app.example.com/oauth/callback/evil

# Bad: Prefix matching
Registered: https://app.example.com/
Valid:      https://app.example.com/anything <- Dangerous

6. References