Open Redirect

Open Redirect is a vulnerability where an application accepts a user-controlled URL parameter and redirects users to that URL without proper validation. Attackers exploit this to redirect victims to malicious sites, making phishing attacks more convincing.

How It Works

Applications often redirect users after certain actions (login, logout, form submission). When the redirect destination comes from user input without validation, attackers can craft links that appear to point to a trusted domain but redirect to a malicious site.

Vulnerable Patterns

// Vulnerable redirect implementations
https://trusted.com/redirect?url=https://evil.com
https://trusted.com/login?next=https://evil.com
https://trusted.com/go?to=https://evil.com/phish
https://trusted.com/out?link=//evil.com

// Vulnerable server code (Node.js)
app.get('/redirect', (req, res) => {
  res.redirect(req.query.url);  // No validation!
});

Bypass Techniques

# Protocol-relative URLs
//evil.com

# URL encoding
https://trusted.com/redirect?url=https%3A%2F%2Fevil.com

# Using @ to fake domain
https://trusted.com@evil.com/page

# Backslash confusion (Windows/some parsers)
https://trusted.com/redirect?url=https:/\evil.com

# Data URI (in some contexts)
data:text/html,<script>location='https://evil.com'</script>

# Domain confusion
https://trusted.com.evil.com
https://trusted-com.evil.com
https://eviltrusted.com

# Whitespace/null byte injection
https://trusted.com/redirect?url=https://evil.com%00.trusted.com

# Double URL encoding
https://trusted.com/redirect?url=%2568ttps://evil.com

Impact

  • Phishing: Convincing users they're on trusted site while stealing credentials
  • OAuth token theft: Redirect OAuth callbacks to attacker-controlled domain
  • SSRF chain: Combine with SSRF to access internal URLs
  • XSS via javascript: javascript:alert(1) in some implementations
  • Malware distribution: Redirect to malicious download

OAuth/OIDC Token Theft

# OAuth flow with open redirect
1. Attacker crafts: https://trusted.com/oauth/callback?redirect=/redirect?url=https://evil.com
2. User authenticates via OAuth
3. OAuth provider redirects to trusted.com with token in fragment
4. Trusted.com's open redirect sends user to evil.com
5. Token may leak via Referer header or if preserved in fragment

Prevention

  • Allowlist: Only allow redirects to known-good URLs or paths
  • Relative paths only: Reject absolute URLs, only allow /local/paths
  • Domain validation: Parse URL and verify hostname against allowlist
  • Indirect references: Use IDs that map to allowed destinations
  • Warning page: Show interstitial warning before external redirects

Safe Implementation

// Safe redirect with allowlist
const allowedHosts = ['trusted.com', 'sub.trusted.com'];

function safeRedirect(url) {
  try {
    const parsed = new URL(url, 'https://trusted.com');
    if (allowedHosts.includes(parsed.hostname)) {
      return parsed.href;
    }
  } catch (e) {}
  return '/';  // Default to home
}

// Or: Only allow relative paths
function isRelativePath(url) {
  return url.startsWith('/') && !url.startsWith('//');
}

See Also