28 KiB
OAuth vers la prise de contrôle de compte
Apprenez le piratage AWS de zéro à héros avec htARTE (HackTricks AWS Red Team Expert)!
Autres moyens de soutenir HackTricks :
- Si vous souhaitez voir votre entreprise annoncée dans HackTricks ou télécharger HackTricks en PDF, consultez les PLANS D'ABONNEMENT !
- Obtenez le merchandising officiel PEASS & HackTricks
- Découvrez La Famille PEASS, notre collection d'NFTs exclusifs
- Rejoignez le 💬 groupe Discord ou le groupe Telegram ou suivez moi sur Twitter 🐦 @carlospolopm.
- Partagez vos astuces de piratage en soumettant des PR aux dépôts github HackTricks et HackTricks Cloud.
Informations de base
Il existe plusieurs versions d'OAuth, vous pouvez lire https://oauth.net/2/ pour obtenir une compréhension de base.
Dans cet article, nous nous concentrerons sur le flux le plus courant que vous rencontrerez aujourd'hui, qui est le type d'autorisation de code d'autorisation OAuth 2.0. En essence, OAuth fournit aux développeurs un mécanisme d'autorisation permettant à une application d'accéder à des données ou d'effectuer certaines actions contre votre compte, depuis une autre application (le serveur d'autorisation).
Par exemple, disons que le site https://yourtweetreader.com a une fonctionnalité pour afficher tous les tweets que vous avez jamais envoyés, y compris les tweets privés. Pour ce faire, OAuth 2.0 est introduit. https://yourtweetreader.com vous demandera d'autoriser leur application Twitter à accéder à tous vos Tweets. Une page de consentement apparaîtra sur https://twitter.com affichant quelles permissions sont demandées, et qui est le développeur qui les demande. Une fois que vous autorisez la demande, https://yourtweetreader.com sera capable d'accéder à vos Tweets en votre nom.
Éléments importants à comprendre dans un contexte OAuth 2.0 :
- propriétaire de la ressource : Le
propriétaire de la ressource
est l'utilisateur/entité accordant l'accès à leur ressource protégée, comme leurs Tweets de compte Twitter. Dans cet exemple, ce serait vous. - serveur de ressources : Le
serveur de ressources
est le serveur gérant les requêtes authentifiées après que l'application a obtenu unjeton d'accès
au nom dupropriétaire de la ressource
. Dans cet exemple, ce serait https://twitter.com - application cliente : L'
application cliente
est l'application demandant l'autorisation dupropriétaire de la ressource
. Dans cet exemple, ce serait https://yourtweetreader.com. - serveur d'autorisation : Le
serveur d'autorisation
est le serveur émettant desjetons d'accès
à l'application cliente
après avoir authentifié avec succès lepropriétaire de la ressource
et obtenu l'autorisation. Dans l'exemple ci-dessus, ce serait https://twitter.com - client_id : Le
client_id
est l'identifiant de l'application. C'est un identifiant unique public, non secret. - client_secret : Le
client_secret
est un secret connu uniquement de l'application et du serveur d'autorisation. Il est utilisé pour générer desjetons d'accès
- response_type : Le
response_type
est une valeur détaillant quel type de jeton est demandé, tel quecode
- scope : Le
scope
est le niveau d'accès demandé que l'application cliente
demande aupropriétaire de la ressource
- redirect_uri : Le
redirect_uri
est l'URL vers laquelle l'utilisateur est redirigé après que l'autorisation est complète. Cela doit généralement correspondre à l'URL de redirection que vous avez préalablement enregistrée avec le service - state : Le paramètre
state
peut conserver des données entre le moment où l'utilisateur est dirigé vers le serveur d'autorisation et son retour. Il est important que cela soit une valeur unique car il sert de mécanisme de protection contre les CSRF s'il contient une valeur unique ou aléatoire par requête - grant_type : Le paramètre
grant_type
explique quel est le type de subvention, et quel jeton va être retourné - code : Ce
code
est le code d'autorisation reçu duserveur d'autorisation
qui sera dans le paramètre de chaîne de requête “code” dans cette requête. Ce code est utilisé conjointement avec leclient_id
et leclient_secret
par l'application cliente pour récupérer unjeton d'accès
- access_token : Le
access_token
est le jeton que l'application cliente utilise pour effectuer des requêtes API au nom d'unpropriétaire de la ressource
- refresh_token : Le
refresh_token
permet à une application d'obtenir un nouveaujeton d'accès
sans solliciter l'utilisateur
Exemple réel
En rassemblant tout cela, voici à quoi ressemble un flux OAuth réel :
- Vous visitez https://yourtweetreader.com et cliquez sur le bouton “Intégrer avec Twitter”.
- https://yourtweetreader.com envoie une demande à https://twitter.com vous demandant, en tant que propriétaire de la ressource, d'autoriser l'application Twitter de https://yourtweetreader.com à accéder à vos Tweets. La demande ressemblera à :
https://twitter.com/auth
?response_type=code
&client_id=yourtweetreader_clientId
&redirect_uri=https%3A%2F%2Fyourtweetreader.com%2Fcallback
&scope=readTweets
&state=kasodk9d1jd992k9klaskdh123
3. Une page de consentement s'affichera :
4. Une fois accepté, Twitter enverra une requête au redirect_uri
avec les paramètres code
et state
:
https://yourtweetreader.com?code=asd91j3jd91j92j1j9d1&state=kasodk9d1jd992k9klaskdh123
5. https://yourtweetreader.com va ensuite prendre ce code
, et en utilisant l'client_id
et l'client_secret
de leur application, va faire une demande depuis le serveur pour récupérer un access_token
en votre nom, ce qui leur permettra d'accéder aux permissions auxquelles vous avez consenti :
POST /oauth/access_token
Host: twitter.com
...{"client_id": "yourtweetreader_clientId", "client_secret": "yourtweetreader_clientSecret", "code": "asd91j3jd91j92j1j9d1", "grant_type": "authorization_code"}
6. Finalement, le flux est complet et https://yourtweetreader.com effectuera un appel API à Twitter avec votre access_token
pour accéder à vos Tweets.
Découvertes de Bug Bounty
Maintenant, la partie intéressante ! Il y a beaucoup de choses qui peuvent mal tourner dans une implémentation OAuth, voici les différentes catégories de bugs que je vois fréquemment :
Configuration faible de redirect_uri
Le redirect_uri
est très important car des données sensibles, telles que le code
, sont ajoutées à cette URL après autorisation. Si le redirect_uri
peut être redirigé vers un serveur contrôlé par un attaquant, cela signifie que l'attaquant peut potentiellement prendre le contrôle du compte d'une victime en utilisant le code
lui-même, et en accédant aux données de la victime.
La manière dont cela va être exploité variera selon le serveur d'autorisation. Certains vont uniquement accepter le chemin redirect_uri
exact spécifié dans l'application cliente, mais certains vont accepter n'importe quoi dans le même domaine ou sous-répertoire du redirect_uri
.
Selon la logique gérée par le serveur, il existe un certain nombre de techniques pour contourner un redirect_uri
. Dans une situation où un redirect_uri
est https://yourtweetreader.com/callback, celles-ci incluent :
- Redirections ouvertes :
https://yourtweetreader.com
/callback?redirectUrl=https://evil.com
- Traversée de chemin :
https://yourtweetreader.com/callback/../redirect?url=https://evil.com
- Regexes faibles de
redirect_uri
:https://yourtweetreader.com.evil.com
- Injection HTML et vol de tokens via l'en-tête referer :
https://yourtweetreader.com/callback/home/attackerimg.jpg
D'autres paramètres qui peuvent être vulnérables aux Redirections Ouvertes sont :
- client_uri - URL de la page d'accueil de l'application cliente
- policy_uri - URL que l'application cliente Partie Fiable fournit pour que l'utilisateur final puisse lire comment ses données de profil seront utilisées.
- tos_uri - URL que l'application cliente Partie Fiable fournit pour que l'utilisateur final puisse lire les conditions de service de la Partie Fiable.
- initiate_login_uri - URI utilisant le schéma https qui peut être utilisé par un tiers pour initier une connexion par le RP. Devrait également être utilisé pour la redirection côté client.
Tous ces paramètres sont optionnels selon les spécifications OAuth et OpenID et ne sont pas toujours pris en charge sur un serveur particulier, il est donc toujours utile d'identifier quels paramètres sont pris en charge sur votre serveur.
Si vous ciblez un serveur OpenID, le point de découverte à **.well-known/openid-configuration
** contient parfois des paramètres tels que "registration_endpoint", "request_uri_parameter_supported", et "require_request_uri_registration". Ceux-ci peuvent vous aider à trouver le point de terminaison d'inscription et d'autres valeurs de configuration du serveur.
XSS dans l'implémentation de redirection
Comme mentionné dans ce rapport de bug bounty https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html il se peut que l'URL de redirection soit reflétée dans la réponse du serveur après l'authentification de l'utilisateur, étant vulnérable au XSS. Payload possible à tester :
https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard</script><h1>test</h1>
CSRF - Gestion incorrecte du paramètre state
Très souvent, le paramètre state
est complètement omis ou utilisé de manière incorrecte. Si un paramètre state
est inexistant, ou une valeur statique qui ne change jamais, le flux OAuth sera très probablement vulnérable au CSRF. Parfois, même s'il existe un paramètre state
, l'application peut ne faire aucune validation de ce paramètre et une attaque fonctionnera. La manière d'exploiter cela serait de passer par le processus d'autorisation sur votre propre compte, et de mettre en pause juste après avoir autorisé. Vous rencontrerez alors une requête telle que :
https://yourtweetreader.com?code=asd91j3jd91j92j1j9d1
Après avoir reçu cette requête, vous pouvez alors abandonner la requête car ces codes sont généralement à usage unique. Vous pouvez ensuite envoyer cette URL à un utilisateur connecté, et cela ajoutera votre compte à leur compte. Au premier abord, cela peut ne pas sembler très sensible puisque vous ajoutez simplement votre compte à celui d'une victime. Cependant, de nombreuses implémentations OAuth sont utilisées à des fins de connexion, donc si vous pouvez ajouter votre compte Google qui est utilisé pour vous connecter, vous pourriez potentiellement réaliser une prise de contrôle de compte en un seul clic, car se connecter avec votre compte Google vous donnerait accès au compte de la victime.
Vous pouvez trouver un exemple à ce sujet dans ce compte-rendu de CTF et dans la machine HTB appelée Oouch.
J'ai également vu le paramètre state
utilisé comme valeur de redirection supplémentaire à plusieurs reprises. L'application utilisera redirect_uri
pour la redirection initiale, mais ensuite le paramètre state
comme une seconde redirection qui pourrait contenir le code
dans les paramètres de requête, ou l'en-tête referer.
Un point important à noter est que cela ne s'applique pas seulement aux situations de connexion et de prise de contrôle de compte. J'ai vu des mauvaises configurations dans :
- Les intégrations Slack permettant à un attaquant d'ajouter leur compte Slack comme destinataire de toutes les notifications/messages
- Les intégrations Stripe permettant à un attaquant de remplacer les informations de paiement et d'accepter les paiements des clients de la victime
- Les intégrations PayPal permettant à un attaquant d'ajouter leur compte PayPal au compte de la victime, ce qui déposerait l'argent sur le PayPal de l'attaquant
Avant la prise de contrôle de compte
L'un des autres problèmes courants que je vois est lorsque les applications permettent de "Se connecter avec X" mais aussi avec un nom d'utilisateur/mot de passe. Il y a 2 façons différentes d'attaquer cela :
- Si l'application ne nécessite pas de vérification de l'email lors de la création du compte, essayez de créer un compte avec l'adresse email d'une victime et un mot de passe d'attaquant avant que la victime ne se soit enregistrée. Si la victime essaie ensuite de s'enregistrer ou de se connecter avec un tiers, comme Google, il est possible que l'application fasse une recherche, voie que l'email est déjà enregistré, puis lie leur compte Google au compte créé par l'attaquant. C'est une "prise de contrôle de compte préalable" où un attaquant aura accès au compte de la victime s'il l'a créé avant que la victime ne s'enregistre.
- Si une application OAuth ne nécessite pas de vérification de l'email, essayez de vous inscrire avec cette application OAuth puis changez l'adresse email pour une adresse email de la victime. Le même problème que ci-dessus pourrait exister, mais vous l'attaqueriez dans l'autre sens et obtiendriez l'accès au compte de la victime pour une prise de contrôle de compte.
Divulgation de secrets
Il est très important de reconnaître quels paramètres OAuth sont secrets, et de les protéger. Par exemple, divulguer le client_id
est parfaitement acceptable et nécessaire, mais divulguer le client_secret
est dangereux. Si cela est divulgué, l'attaquant peut potentiellement abuser de la confiance et de l'identité de l'application cliente de confiance pour voler les access_tokens
des utilisateurs et les informations/accès privés pour leurs comptes intégrés. Pour revenir à notre exemple précédent, un problème que j'ai vu est d'effectuer cette étape depuis le client, au lieu du serveur :
5. https://yourtweetreader.com prendra ensuite ce code
, et en utilisant l'client_id
et l'client_secret
de leur application, fera une requête depuis le serveur pour récupérer un access_token
en votre nom, ce qui leur permettra d'accéder aux permissions auxquelles vous avez consenti.
Si cela est fait depuis le client, le client_secret
sera divulgué et les utilisateurs pourront générer des access_tokens
au nom de l'application. Avec un peu d'ingénierie sociale, ils peuvent également ajouter plus de scopes à l'autorisation OAuth et tout semblera légitime car la requête proviendra de l'application cliente de confiance.
Bruteforce du Client Secret
Vous pouvez essayer de bruteforcer le client_secret
d'un fournisseur de services avec le fournisseur d'identité afin d'essayer de voler des comptes.
La requête de BF peut ressembler à :
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]
Fuite du Header Referer avec Code + État
Une fois que le client a le code et l'état, s'ils sont reflétés dans le header Referer lorsqu'il navigue vers une autre page, alors il est vulnérable.
Jeton d'Accès Stocké dans l'Historique du Navigateur
Allez dans l'historique du navigateur et vérifiez si le jeton d'accès y est enregistré.
Code d'Autorisation Éternel
Le code d'autorisation devrait avoir une durée de vie limitée pour réduire la fenêtre de temps pendant laquelle un attaquant peut le voler et l'utiliser.
Jeton d'Autorisation/Actualisation non lié au client
Si vous pouvez obtenir le code d'autorisation et l'utiliser avec un client différent, alors vous pouvez prendre le contrôle d'autres comptes.
Chemins Heureux, XSS, Iframes & Messages Post pour fuite de code & valeurs d'état
AWS Cognito
Dans ce rapport de bug bounty : https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/ vous pouvez voir que le token que AWS Cognito renvoie à l'utilisateur peut avoir assez de permissions pour écraser les données de l'utilisateur. Par conséquent, si vous pouvez changer l'email de l'utilisateur pour un autre email d'utilisateur, vous pourriez être capable de prendre le contrôle d'autres comptes.
# 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"
}
]
}
Pour plus d'informations détaillées sur la manière d'abuser d'AWS Cognito, consultez :
{% embed url="https://cloud.hacktricks.xyz/pentesting-cloud/aws-pentesting/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum" %}
Abuser des tokens d'autres applications
Comme mentionné dans ce compte-rendu, les flux OAuth qui s'attendent à recevoir le token (et non un code) pourraient être vulnérables s'ils ne vérifient pas que le token appartient à l'application.
Cela est dû au fait qu'un attaquant pourrait créer une application prenant en charge OAuth et se connecter avec Facebook (par exemple) dans sa propre application. Ensuite, une fois qu'une victime se connecte avec Facebook dans l'application de l'attaquant, l'attaquant pourrait obtenir le token OAuth de l'utilisateur donné à son application, et l'utiliser pour se connecter dans l'application OAuth de la victime en utilisant le token de l'utilisateur de la victime.
{% hint style="danger" %} Par conséquent, si l'attaquant parvient à faire accéder l'utilisateur à sa propre application OAuth, il pourra prendre le contrôle du compte de la victime dans les applications qui s'attendent à un token et qui ne vérifient pas si le token a été accordé à leur ID d'application. {% endhint %}
Deux liens & cookie
Selon ce compte-rendu, il était possible de faire ouvrir par une victime une page avec un returnUrl pointant vers l'hôte de l'attaquant. Cette information serait stockée dans un cookie (RU) et dans une étape ultérieure, l'invite demandera à l'utilisateur s'il souhaite donner accès à cet hôte de l'attaquant.
Pour contourner cette invite, il était possible d'ouvrir un onglet pour initier le flux Oauth qui définirait ce cookie RU en utilisant le returnUrl, de fermer l'onglet avant que l'invite ne soit affichée, et d'ouvrir un nouvel onglet sans cette valeur. Ensuite, l'invite n'informera pas sur l'hôte de l'attaquant, mais le cookie serait défini pour lui, donc le token sera envoyé à l'hôte de l'attaquant dans la redirection.
Paramètres SSRFs
L'une des URL cachées que vous pourriez manquer est le point de terminaison d'enregistrement de client dynamique. Afin d'authentifier les utilisateurs avec succès, les serveurs OAuth doivent connaître les détails de l'application cliente, tels que le "client_name", "client_secret", "redirect_uris", etc. Ces détails peuvent être fournis via une configuration locale, mais les serveurs d'autorisation OAuth peuvent également avoir un point de terminaison d'enregistrement spécial. Ce point de terminaison est normalement mappé sur "/register" et accepte les requêtes POST avec le format suivant :
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"]
}
Il existe deux spécifications qui définissent les paramètres dans cette requête : [RFC7591](https://tools.ietf.org/html/rfc7591) pour OAuth et [Openid Connect Registration 1.0](https://openid.net/specs/openid-connect-registration-1_0.html#rfc.section.3.1).
Comme vous pouvez le voir ici, un certain nombre de ces valeurs sont transmises via des références URL et semblent être des cibles potentielles pour [Server Side Request Forgery](https://portswigger.net/web-security/ssrf). En même temps, la plupart des serveurs que nous avons testés ne résolvent pas immédiatement ces URL lorsqu'ils reçoivent une demande d'inscription. Au lieu de cela, ils **enregistrent simplement ces paramètres et les utilisent plus tard pendant le flux d'autorisation OAuth**. En d'autres termes, c'est plus comme un SSRF de second ordre, ce qui rend la détection en boîte noire plus difficile.
Les paramètres suivants sont particulièrement intéressants pour les attaques SSRF :
* **logo\_uri** - URL qui fait référence à un **logo pour l'application cliente**. **Après avoir enregistré un client**, vous pouvez essayer d'appeler le point de terminaison d'autorisation OAuth ("/authorize") en utilisant votre nouveau "client\_id". Après la connexion, le serveur vous demandera d'approuver la demande et **peut afficher l'image à partir du "logo\_uri"**. Si le **serveur récupère l'image par lui-même**, le SSRF devrait être déclenché par cette étape. Alternativement, le serveur peut simplement inclure le logo via une balise **client-side "\<img>"**. Bien que cela ne conduise pas à SSRF, cela peut conduire à **XSS si l'URL n'est pas échappée**.
* **jwks\_uri** - URL pour le document JSON Web Key Set \[JWK] du client. Ce jeu de clés est nécessaire sur le serveur pour valider les requêtes signées faites au point de terminaison du jeton lors de l'utilisation de JWT pour l'authentification du client \[RFC7523]. Pour tester le SSRF dans ce paramètre, **enregistrez une nouvelle application cliente avec un "jwks\_uri" malveillant**, effectuez le processus d'autorisation pour **obtenir un code d'autorisation pour n'importe quel utilisateur, puis récupérez le point de terminaison "/token"** avec le corps suivant :
`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 vulnérable, le serveur devrait effectuer une requête HTTP de serveur à serveur vers le "jwks_uri" fourni car il a besoin de cette clé pour vérifier la validité du paramètre "client_assertion" dans votre requête. Cela sera probablement seulement une vulnérabilité SSRF aveugle, car le serveur attend une réponse JSON appropriée.
- sector_identifier_uri - Cette URL fait référence à un fichier avec un seul tableau JSON de valeurs redirect_uri. Si pris en charge, le serveur peut récupérer cette valeur dès que vous soumettez la demande d'inscription dynamique. Si cela n'est pas récupéré immédiatement, essayez d'effectuer une autorisation pour ce client sur le serveur. Comme il a besoin de connaître les redirect_uris pour compléter le flux d'autorisation, cela forcera le serveur à faire une requête à votre sector_identifier_uri malveillant.
- request_uris - Un tableau des request_uris autorisés pour ce client. Le paramètre "request_uri" peut être pris en charge sur le point de terminaison d'autorisation pour fournir une URL qui contient un JWT avec les informations de la demande (voir https://openid.net/specs/openid-connect-core-1_0.html#rfc.section.6.2).
Même si l'inscription dynamique du client n'est pas activée, ou si elle nécessite une authentification, nous pouvons essayer de réaliser un SSRF sur le point de terminaison d'autorisation simplement en utilisant "request_uri":\
GET /authorize?response_type=code%20id_token&client_id=sclient1&request_uri=https://ybd1rc7ylpbqzygoahtjh6v0frlh96.burpcollaborator.net/request.jwt
Note : ne confondez pas ce paramètre avec "redirect_uri". Le "redirect_uri" est utilisé pour la redirection après autorisation, tandis que "request_uri" est récupéré par le serveur au début du processus d'autorisation.
En même temps, de nombreux serveurs que nous avons vus n'autorisent pas des valeurs "request_uri" arbitraires : ils n'autorisent que des URL préalablement enregistrées pendant le processus d'inscription du client. C'est pourquoi nous devons fournir "request_uris": "https://ybd1rc7ylpbqzygoahtjh6v0frlh96.burpcollaborator.net/request.jwt" au préalable.
Conditions de course chez les fournisseurs OAuth
Si la plateforme que vous testez est un fournisseur OAuth lisez ceci pour tester d'éventuelles conditions de course.
Références
- https://medium.com/a-bugz-life/the-wondeful-world-of-oauth-bug-bounty-edition-af3073b354c1
- https://portswigger.net/research/hidden-oauth-attack-vectors
Apprenez le piratage AWS de zéro à héros avec htARTE (HackTricks AWS Red Team Expert)!
Autres moyens de soutenir HackTricks :
- Si vous souhaitez voir votre entreprise annoncée dans HackTricks ou télécharger HackTricks en PDF Consultez les PLANS D'ABONNEMENT!
- Obtenez le merchandising officiel PEASS & HackTricks
- Découvrez La Famille PEASS, notre collection d'NFTs exclusifs
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez moi sur Twitter 🐦 @carlospolopm.
- Partagez vos astuces de piratage en soumettant des PR aux dépôts github HackTricks et HackTricks Cloud.