27 KiB
OAuth para tomar el control de una cuenta
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- ¿Trabajas en una empresa de ciberseguridad? ¿Quieres ver tu empresa anunciada en HackTricks? ¿O quieres tener acceso a la última versión de PEASS o descargar HackTricks en PDF? ¡Consulta los PLANES DE SUSCRIPCIÓN!
- Descubre The PEASS Family, nuestra colección exclusiva de NFTs
- Obtén el swag oficial de PEASS y HackTricks
- Únete al 💬 grupo de Discord o al grupo de telegram o sígueme en Twitter 🐦@carlospolopm.
- Comparte tus trucos de hacking enviando PR al repositorio de hacktricks y al repositorio de hacktricks-cloud.
Información básica
Existen varias versiones de OAuth, puedes leer https://oauth.net/2/ para tener una comprensión básica.
En este artículo, nos centraremos en el flujo más común que encontrarás hoy en día, que es el tipo de concesión de código de autorización OAuth 2.0. En esencia, OAuth proporciona a los desarrolladores un mecanismo de autorización para permitir que una aplicación acceda a datos o realice ciertas acciones en tu cuenta, desde otra aplicación (el servidor de autorización).
Por ejemplo, supongamos que el sitio web https://yourtweetreader.com tiene una funcionalidad para mostrar todos los tweets que has enviado, incluyendo los tweets privados. Para hacer esto, se introduce OAuth 2.0. https://yourtweetreader.com te pedirá que autorices su aplicación de Twitter para acceder a todos tus tweets. Una página de consentimiento aparecerá en https://twitter.com mostrando qué permisos se están solicitando y quién es el desarrollador que lo solicita. Una vez que autorices la solicitud, https://yourtweetreader.com podrá acceder a tus tweets en tu nombre.
Elementos importantes para entender en el contexto de OAuth 2.0:
- propietario de recursos: El
propietario de recursos
es el usuario/entidad que otorga acceso a su recurso protegido, como los tweets de su cuenta de Twitter. En este ejemplo, serías tú. - servidor de recursos: El
servidor de recursos
es el servidor que maneja las solicitudes autenticadas después de que la aplicación haya obtenido untoken de acceso
en nombre delpropietario de recursos
. En este ejemplo, sería https://twitter.com - aplicación cliente: La
aplicación cliente
es la aplicación que solicita autorización delpropietario de recursos
. En este ejemplo, sería https://yourtweetreader.com. - servidor de autorización: El
servidor de autorización
es el servidor que emitetokens de acceso
a laaplicación cliente
después de autenticar con éxito alpropietario de recursos
y obtener autorización. En el ejemplo anterior, sería https://twitter.com - client_id: El
client_id
es el identificador de la aplicación. Este es un identificador único público y no secreto. - client_secret: El
client_secret
es un secreto conocido solo por la aplicación y el servidor de autorización. Esto se utiliza para generaraccess_tokens
- response_type: El
response_type
es un valor que detalla qué tipo de token se está solicitando, comocode
- scope: El
scope
es el nivel de acceso solicitado que laaplicación cliente
está solicitando delpropietario de recursos
- redirect_uri: El
redirect_uri
es la URL a la que se redirige al usuario después de que se complete la autorización. Por lo general, esto debe coincidir con la URL de redireccionamiento que has registrado previamente con el servicio - state: El parámetro
state
puede persistir datos entre la dirección del usuario al servidor de autorización y viceversa. Es importante que este sea un valor único ya que sirve como un mecanismo de protección CSRF si contiene un valor único o aleatorio por solicitud - grant_type: El parámetro
grant_type
explica cuál es el tipo de concesión y qué token se va a devolver - code: Este
code
es el código de autorización recibido delservidor de autorización
que estará en el parámetro de cadena de consulta "code" en esta solicitud. Este código se utiliza junto con elclient_id
yclient_secret
por la aplicación cliente para obtener unaccess_token
- access_token: El
access_token
es el token que la aplicación cliente utiliza para hacer solicitudes de API en nombre de unpropietario de recursos
- refresh_token: El
refresh_token
permite a una aplicación obtener un nuevoaccess_token
sin solicitar al usuario
Ejemplo real
Poniendo todo esto junto, aquí está lo que parece un flujo real de OAuth:
- Visitas https://yourtweetreader.com y haces clic en el botón "Integrar con Twitter".
- https://yourtweetreader.com envía una solicitud a https://twitter.com pidiéndote, el propietario de recursos, que autorices la aplicación de Twitter de https://yourtweetreader.com a acceder a tus tweets. La solicitud se verá así:
https://twitter.com/auth
?response_type=code
&client_id=yourtweetreader_clientId
&redirect_uri=https%3A%2F%2Fyourtweetreader.com%2Fcallback
&scope=readTweets
&state=kasodk9d1jd992k9klaskdh123
3. Se le pedirá que acepte una página de consentimiento:
4. Una vez aceptado, Twitter enviará una solicitud de vuelta a la redirect_uri
con los parámetros code
y state
:
https://yourtweetreader.com?code=asd91j3jd91j92j1j9d1&state=kasodk9d1jd992k9klaskdh123
5. Luego, https://yourtweetreader.com tomará ese código
, y utilizando el client_id
y client_secret
de su aplicación, hará una solicitud desde el servidor para recuperar un access_token
en su nombre, lo que les permitirá acceder a los permisos a los que usted consintió:
POST /oauth/access_token
Host: twitter.com
...{"client_id": "yourtweetreader_clientId", "client_secret": "yourtweetreader_clientSecret", "code": "asd91j3jd91j92j1j9d1", "grant_type": "authorization_code"}
6. Finalmente, el flujo está completo y https://yourtweetreader.com hará una llamada API a Twitter con su access_token
para acceder a sus Tweets.
Hallazgos de recompensa por errores
¡Ahora viene la parte interesante! Hay muchas cosas que pueden salir mal en una implementación de OAuth, aquí están las diferentes categorías de errores que veo con frecuencia:
Configuración débil de redirect_uri
El redirect_uri
es muy importante porque datos sensibles, como el code
, se agregan a esta URL después de la autorización. Si el redirect_uri
puede ser redirigido a un servidor controlado por un atacante, esto significa que el atacante potencialmente puede tomar el control de la cuenta de una víctima usando el code
ellos mismos y obteniendo acceso a los datos de la víctima.
La forma en que esto se va a explotar va a variar según el servidor de autorización. Algunos solo aceptarán la misma ruta exacta de redirect_uri
especificada en la aplicación cliente, pero algunos aceptarán cualquier cosa en el mismo dominio o subdirectorio de redirect_uri
.
Dependiendo de la lógica manejada por el servidor, hay una serie de técnicas para evitar un redirect_uri
. En una situación en la que un redirect_uri
es https://yourtweetreader.com/callback, estas incluyen:
- Redirecciones abiertas:
https://yourtweetreader.com
/callback?redirectUrl=https://evil.com
- Traversal de ruta:
https://yourtweetreader.com/callback/../redirect?url=https://evil.com
- Regexes débiles de
redirect_uri
:https://yourtweetreader.com.evil.com
- Inyección de HTML y robo de tokens a través del encabezado de referencia:
https://yourtweetreader.com/callback/home/attackerimg.jpg
Otros parámetros que pueden ser vulnerables a Redirecciones Abiertas son:
- client_uri - URL de la página de inicio de la aplicación cliente
- policy_uri - URL que el cliente de Relying Party proporciona para que el usuario final pueda leer sobre cómo se utilizarán sus datos de perfil.
- tos_uri - URL que el cliente de Relying Party proporciona para que el usuario final pueda leer sobre los términos de servicio de Relying Party.
- initiate_login_uri - URI que un tercero puede usar para iniciar sesión en el RP. También debe usarse para la redirección del lado del cliente.
Todos estos parámetros son opcionales según las especificaciones de OAuth y OpenID y no siempre son compatibles en un servidor en particular, por lo que siempre vale la pena identificar qué parámetros son compatibles en su servidor.
Si apunta a un servidor OpenID, el punto de descubrimiento en **.well-known/openid-configuration
** a veces contiene parámetros como "registration_endpoint", "request_uri_parameter_supported" y "require_request_uri_registration". Estos pueden ayudarlo a encontrar el punto final de registro y otros valores de configuración del servidor.
XSS en la implementación de redirección
Como se menciona en este informe de recompensa por errores https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html, es posible que la URL de redirección se refleje en la respuesta del servidor después de que el usuario se autentique, siendo vulnerable a XSS. Carga útil posible para probar:
https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard</script><h1>test</h1>
CSRF - Manejo inadecuado del parámetro de estado
Muy a menudo, el parámetro state
se omite completamente o se utiliza de manera incorrecta. Si un parámetro de estado es inexistente o un valor estático que nunca cambia, el flujo de OAuth probablemente será vulnerable a CSRF. A veces, incluso si hay un parámetro state
, la aplicación puede no validar el parámetro y un ataque funcionará. La forma de explotar esto sería pasar por el proceso de autorización en su propia cuenta y detenerse justo después de autorizar. Luego encontrará una solicitud como:
https://yourtweetreader.com?code=asd91j3jd91j92j1j9d1
Después de recibir esta solicitud, puedes descartarla porque estos códigos suelen ser de un solo uso. Luego, puedes enviar esta URL a un usuario conectado y se agregará tu cuenta a la de ellos. Al principio, esto puede no parecer muy sensible ya que simplemente estás agregando tu cuenta a la cuenta de la víctima. Sin embargo, muchas implementaciones de OAuth son para fines de inicio de sesión, por lo que si puedes agregar tu cuenta de Google que se utiliza para iniciar sesión, podrías potencialmente realizar una Toma de control de cuenta con un solo clic, ya que iniciar sesión con tu cuenta de Google te daría acceso a la cuenta de la víctima.
Puedes encontrar un ejemplo sobre esto en este writeup de CTF y en la caja HTB llamada Oouch.
También he visto que el parámetro de estado se usa varias veces como un valor de redireccionamiento adicional. La aplicación usará redirect_uri
para la redirección inicial, pero luego el parámetro state
como una segunda redirección que podría contener el code
dentro de los parámetros de consulta o el encabezado de referencia.
Una cosa importante a tener en cuenta es que esto no solo se aplica a situaciones de inicio de sesión y toma de control de cuenta. He visto configuraciones incorrectas en:
- Integraciones de Slack que permiten a un atacante agregar su cuenta de Slack como destinatario de todas las notificaciones/mensajes
- Integraciones de Stripe que permiten a un atacante sobrescribir la información de pago y aceptar pagos de los clientes de la víctima
- Integraciones de PayPal que permiten a un atacante agregar su cuenta de PayPal a la cuenta de la víctima, lo que depositaría dinero en la cuenta de PayPal del atacante
Pre Toma de control de cuenta
Uno de los problemas más comunes que veo es cuando las aplicaciones permiten "Iniciar sesión con X" pero también con nombre de usuario/contraseña. Hay 2 formas diferentes de atacar esto:
- Si la aplicación no requiere verificación de correo electrónico en la creación de la cuenta, intenta crear una cuenta con la dirección de correo electrónico de la víctima y una contraseña de atacante antes de que la víctima se haya registrado. Si la víctima luego intenta registrarse o iniciar sesión con un tercero, como Google, es posible que la aplicación haga una búsqueda, vea que el correo electrónico ya está registrado y luego vincule la cuenta creada por el atacante a la cuenta de Google de la víctima. Esto es una "pre toma de control de cuenta" donde un atacante tendrá acceso a la cuenta de la víctima si la creó antes de que la víctima se registrara.
- Si una aplicación OAuth no requiere verificación de correo electrónico, intenta registrarte con esa aplicación OAuth con la dirección de correo electrónico de la víctima. El mismo problema que se mencionó anteriormente podría existir, pero estarías atacándolo desde la otra dirección y obteniendo acceso a la cuenta de la víctima para una toma de control de cuenta.
Divulgación de secretos
Es muy importante reconocer cuáles de los muchos parámetros de OAuth son secretos y protegerlos. Por ejemplo, filtrar el client_id
es perfectamente aceptable y necesario, pero filtrar el client_secret
es peligroso. Si esto se filtra, el atacante puede potencialmente abusar de la confianza e identidad de la aplicación cliente de confianza para robar los access_tokens
de los usuarios y la información/acceso privado para sus cuentas integradas. Volviendo a nuestro ejemplo anterior, un problema que he visto es realizar este paso desde el cliente, en lugar del servidor:
5. https://yourtweetreader.com luego tomará ese code
y, utilizando el client_id
y el client_secret
de su aplicación, hará una solicitud desde el servidor para recuperar un access_token
en tu nombre, lo que les permitirá acceder a los permisos a los que has consentido.
Si esto se hace desde el cliente, el client_secret
se filtrará y los usuarios podrán generar access_tokens
en nombre de la aplicación. Con algo de ingeniería social, también pueden agregar más alcances a la autorización de OAuth y todo parecerá legítimo ya que la solicitud vendrá de la aplicación cliente de confianza.
Fuerza bruta de secretos del cliente
Puedes intentar atacar por fuerza bruta el client_secret de un proveedor de servicios con el proveedor de identidad para intentar robar cuentas.
La solicitud 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]
Fuga de cabecera Referer con código y estado
Una vez que el cliente tiene el código y el estado, si se refleja dentro de la cabecera Referer cuando navega a una página diferente, entonces es vulnerable.
Token de acceso almacenado en el historial del navegador
Vaya al historial del navegador y compruebe si el token de acceso está guardado allí.
Código de autorización eterno
El código de autorización debe vivir solo por un tiempo para limitar la ventana de tiempo en la que un atacante puede robarlo y usarlo.
Token de autorización/actualización no vinculado al cliente
Si puede obtener el código de autorización y usarlo con un cliente diferente, entonces puede tomar el control de otras cuentas.
Caminos felices, XSS, iframes y mensajes de publicación para filtrar valores de código y estado
AWS Cognito
En este informe de recompensa por errores: https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/ puede ver que el token que AWS Cognito devuelve al usuario puede tener suficientes permisos para sobrescribir los datos del usuario. Por lo tanto, si puede cambiar el correo electrónico del usuario por un correo electrónico de usuario diferente, podría tomar el control de otras cuentas.
# 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 obtener información detallada sobre cómo abusar de AWS Cognito, consulte:
{% embed url="https://cloud.hacktricks.xyz/pentesting-cloud/aws-pentesting/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum" %}
Dos enlaces y cookie
Según este artículo, era posible hacer que una víctima abriera una página con un returnUrl que apuntara 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 flujo de Oauth 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 se establecerá en él, por lo que el token se enviará al host del atacante en la redirección.
Parámetros SSRF
Una de las URL ocultas que puede pasar por alto es el punto final de registro de cliente dinámico. Para autenticar con éxito a los usuarios, los servidores OAuth necesitan conocer detalles sobre la aplicación cliente, como el "client_name", "client_secret", "redirect_uris", y así sucesivamente. Estos detalles se pueden proporcionar mediante la configuración local, pero los servidores de autorización OAuth también pueden tener un punto final de registro especial. Este punto final normalmente se asigna a "/register" y acepta solicitudes POST con el siguiente formato:
POST /connect/register HTTP/1.1
Content-Type: application/json
Host: server.example.com
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJ ...
{
"application_type": "web",
"redirect_uris": ["https://client.example.org/callback"],
"client_name": "My Example",
"logo_uri": "https://client.example.org/logo.png",
"subject_type": "pairwise",
"sector_identifier_uri": "https://example.org/rdrct_uris.json",
"token_endpoint_auth_method": "client_secret_basic",
"jwks_uri": "https://client.example.org/public_keys.jwks",
"contacts": ["ve7jtb@example.org"],
"request_uris": ["https://client.example.org/rf.txt"]
}
Hay dos especificaciones que definen los parámetros en esta solicitud: RFC7591 para OAuth y Openid Connect Registration 1.0.
Como se puede ver aquí, varios de estos valores se pasan a través de referencias URL y parecen ser posibles objetivos para Server Side Request Forgery. Al mismo tiempo, la mayoría de los servidores que hemos probado no resuelven estas URL inmediatamente cuando reciben una solicitud de registro. En su lugar, simplemente guardan estos parámetros y los usan más tarde durante el flujo de autorización de OAuth. En otras palabras, esto es más como un SSRF de segundo orden, lo que hace que la detección de caja negra sea más difícil.
Los siguientes parámetros son particularmente interesantes para los ataques SSRF:
-
logo_uri - URL que hace referencia a un logotipo para la aplicación del cliente. Después de registrar un cliente, puedes intentar llamar al punto final de autorización de OAuth ("/authorize") usando tu nuevo "client_id". Después del inicio de sesión, el servidor te pedirá que apruebes la solicitud y puede mostrar la imagen de "logo_uri". Si el servidor recupera la imagen por sí mismo, el SSRF debería ser desencadenado por este paso. Alternativamente, el servidor puede incluir el logotipo a través de una etiqueta "<img>" del lado del cliente. Aunque esto no lleva a SSRF, puede llevar a XSS si la URL no está escapada.
-
jwks_uri - URL para el conjunto de claves JSON del cliente [JWK]. Este conjunto de claves es necesario en el servidor para validar las solicitudes firmadas realizadas en el punto final del token cuando se usan JWT para la autenticación del cliente [RFC7523]. Para probar SSRF en este parámetro, registra una nueva aplicación de cliente con un "jwks_uri" malicioso, realiza el proceso de autorización para obtener un código de autorización para cualquier usuario y luego recupera el punto final "/token" con el siguiente cuerpo:
POST /oauth/token HTTP/1.1
...
``
grant_type=authorization_code&code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=eyJhbGci...
Si es vulnerable, el servidor debería realizar una solicitud HTTP de servidor a servidor a la "jwks_uri" suministrada porque necesita esta clave para verificar la validez del parámetro "client_assertion" en tu solicitud. Esto probablemente solo será una vulnerabilidad de SSRF ciega, ya que el servidor espera una respuesta JSON adecuada.
-
sector_identifier_uri - Esta URL hace referencia a un archivo con una sola matriz JSON de valores redirect_uri. Si es compatible, el servidor puede recuperar este valor tan pronto como envíes la solicitud de registro dinámico. Si esto no se recupera inmediatamente, intenta realizar la autorización para este cliente en el servidor. Como necesita conocer los redirect_uris para completar el flujo de autorización, esto obligará al servidor a hacer una solicitud a tu malintencionado sector_identifier_uri.
-
request_uris - Una matriz de los request_uris permitidos para este cliente. El parámetro "request_uri" puede ser compatible en el punto final de autorización para proporcionar una URL que contenga un JWT con la información de la solicitud (ver https://openid.net/specs/openid-connect-core-1_0.html#rfc.section.6.2).
Incluso si el registro dinámico del cliente no está habilitado, o requiere autenticación, podemos intentar realizar SSRF en el punto final de autorización simplemente usando "request_uri":\
GET /authorize?response_type=code%20id_token&client_id=sclient1&request_uri=https://ybd1rc7ylpbqzygoahtjh6v0frlh96.burpcollaborator.net/request.jwt
Nota: no confundir este parámetro con "redirect_uri". El "redirect_uri" se utiliza para la redirección después de la autorización, mientras que "request_uri" se recupera por el servidor al inicio del proceso de autorización.
Al mismo tiempo, muchos servidores que hemos visto no permiten valores arbitrarios de "request_uri": solo permiten URL en lista blanca que se registraron previamente durante el proceso de registro del cliente. Es por eso que necesitamos suministrar "request_uris": "https://ybd1rc7ylpbqzygoahtjh6v0frlh96.burpcollaborator.net/request.jwt" de antemano.
Condiciones de carrera de los proveedores de OAuth
Si la plataforma que estás probando es un proveedor de OAuth, lee esto para probar posibles condiciones de carrera.
Referencias
- https://medium.com/a-bugz-life/the-wondeful-world-of-oauth-bug-bounty-edition-af3073b354c1
- https://portswigger.net/research/hidden-oauth-attack-vectors
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- ¿Trabajas en una empresa de ciberseguridad? ¿Quieres ver tu empresa anunciada en HackTricks? ¿o quieres tener acceso a la última versión de PEASS o descargar HackTricks en PDF? ¡Consulta los PLANES DE SUSCRIPCIÓN!
- Descubre The PEASS Family, nuestra colección de NFTs exclusivos.
- Consigue el swag oficial de PEASS & HackTricks
- Únete al 💬 grupo de Discord o al grupo de telegram o sígueme en Twitter 🐦@carlospolopm.
- Comparte tus trucos de hacking enviando PR al repositorio de hacktricks y al repositorio de hacktricks-cloud.