Le blog des décideurs du digital sur toutes les tendances tech, architecture, organisation et produit

Un SSO mal configuré et un compte (presque) volé!

Aujourd’hui, pour simplifier le processus de login, de nombreuses applications web permettent à leurs utilisateurs de se connecter via leur compte Google, Apple, Facebook… Le protocole le plus courant qui permet cette fonctionnalité s’appelle OAuth. Nous allons voir comment quelques erreurs d’implémentation peuvent amener à la prise de contrôle totale d’une session utilisateur, comme cela a failli être le cas chez Booking.com.

🕵️ Explication de l'attaque

OAuth est un protocole d’autorisation utilisé par de nombreux services en ligne pour permettre à leurs utilisateurs de se connecter à des applications tierces sans avoir à partager leur nom d'utilisateur et leur mot de passe. A la place, un système de redirection et d’échange de token permet d’identifier l’utilisateur. C’est par exemple le cas quand vous vous connectez à Slack avec votre compte Google : 

Untitled-2Le cas qui nous intéresse aujourd’hui concerne les autorisations d’accès sur Booking.com via Facebook. Entrons plus dans le détail de ce qui se passe :

1ère étape :

L’utilisateur demande à se connecter en cliquant sur le bouton login with Facebook et est redirigé sur une page Facebook. Celle-ci a une url un peu particulière : https://www.facebook.com/v3.0/dialog/oauth?redirect_uri=https://account.booking.com/social/result/facebook&scope=email&client_id=210068525731476&state=[large_object]&response_type=code où l’on a

  • redirect_uri : l’url où sera redirigé l’utilisateur après s’être identifié sur Facebook
  • response_type : ici code, c’est le type de token qui sera retourné à Booking pour terminer l’identification
  • state : un objet pour manipuler le comportement de la page sur laquelle l’utilisateur est redirigé après identification

Flux OAuth - 1

2e étape :

Après s’être identifié sur Facebook, l’utilisateur est redirigé sur l’url de redirection qui est spécifiée dans la redirect_uri enrichie d’un code secret :

https://account.booking.com/social/result/facebook?code=[secret_code]?state=[large_object]

Untitled (2)-2

3e étape :

Booking reprend alors la main et échange le code contre un access token qui est réutilisable et a une durée de vie plus longue en appelant l’url de Facebook : https://graph.facebook.com/oauth/access_token?client_id={client_id}&redirect_uri={redirect_uri}&code={code}&client_secret={client_secret}

Untitled (3)-1

Ce flux s’appelle le Authorization code grant type, il en existe d’autres que vous pouvez retrouver ici.

🥷 Comment l’exploiter ?

Comme le code est envoyé en clair dans l’url de redirection, un attaquant voudrait remplacer la redirect uri pour rediriger vers un site malveillant, ce qui lui permettrait de récupérer le code une fois que l’utilisateur s’est identifié.

Hélas, il n’est pas possible de modifier le domaine de la redirection. Booking a configuré son nom de domaine auprès de Facebook qui ne permettra pas de faire une redirection ailleurs.

Exit donc de mettre redirect_uri=https://hacker.com 

En revanche, à cause d’une mauvaise configuration du SSO, il est possible de modifier le path de redirection, donc les urls du types https://account.booking.com/un/autre/path sont valides ✅

Après s'être identifié sur Facebook, l’utilisateur atterrira donc sur la page : https://account.booking.com/un/autre/path?code=[secret_code]?state=[large_object]

Maintenant il faut trouver une page sur Booking qui va nous permettre d’exfiltrer le code secret.

Hors il se trouve qu’il existe une feature "Add a display name" dans le dashboard qui pour s'assurer que l'utilisateur a bien les bons droits le redirige vers https://account.booking.com/oauth2/authorize?aid=123;client_id=d1cDdLj40ACItEtxJLTo;redirect_uri=https://account.booking.com/settings/oauth_callback;response_type=code;state=eyJteXNldHRpbmdzX3BhdGgiOiIvbXlzZXR0aW5ncy9wZXJzb25hbCIsImFpZCI6IjEyMyJ9

Si l'utilisateur a bien les bons droits et est connecté, il est ensuite redirigé vers la page : https://account.booking.com/mysettings/personal

Vous vous souvenez du state qui permet de manipuler le comportement de la page. Ici ceux qui ont l’oeil remarqueront qu’il est en base64, un format d’encodage pour les chaînes de caractères. Pour ceux qui ne l’ont pas vu, l’indice c’est la chaine de caractère qui commence par `ey` qui correspond à `{` en base 64 😉

En le décodant on découvre qu’il contient

{
mysettings_path: "/mysettings/personal",
aid: 123,
}

Si vous n’avez jamais entendu parlé d’open redirect, je vous recommande d’aller lire notre newsletter sur comment vous pouvez vous faire hacker depuis votre boîte aux lettres.

En tentant de remplacer /mysettings/personal par https://hackers.com, on constate que l’utilisateur est bien redirigé vers notre domaine hacker.com après son identification.

Mais pas de code ! Celui-ci est malheureusement perdu au moment de la redirection car il est contenu dans des query parameters.

Pour contourner ce problème, il suffit de modifier le type de response_type à code,token. Le code sera alors contenu dans les fragments, c’est ce qui vient dans une url après un #

Untitled (4)

Les fragments sont utilisés pour stocker des informations sensibles qui ne doivent pas apparaître dans des logs ou être envoyés au serveur. Par contre, ils sont conservés au moment de la redirection.

Petit récapitulatif de ce qu’il se passe :

  • On envoie cette url à notre victime par exemple dans un mail de phishing qui va trigger un login pour Booking via Facebook
    Untitled (5)
  • La redirect uri, que l’on a fourni en argument, génère une seconde redirection qui ne demande pas de login parce que l’utilisateur est déjà loggé. En revanche le code est bien présent en fragment et est donc conservé
    Untitled (6)
  • On exploite ensuite l’open redirect pour transférer le code sur un domaine contrôlé par l’attaquant: https://hacker.com#code=[secret_code]&access_token=[token]

🎉 Hourra on a le code, il ne nous reste plus qu’à récupérer notre access_token, pour cela on intercepte notre requête de redirection et on remplace le code, ce qui nous donne :

  • Untitled (7)-1Et on reçoit une erreur invalid code…

Et oui, malheureusement le code ayant été obtenu pour une redirect_uri différent, Facebook refuse de nous accorder un access_token

Mais l’histoire ne s’arrête pas là. L’application Android a une faille qui permet de manipuler la redirect_uri et donc de récupérer l’access_token, mais je ne vais pas détailler cette partie ici. Si vous voulez toute l’attaque vous trouverez ici tout le détail.

🛡 Comment se protéger ?

  • Faites attention à ce que vous recevez par mails en particulier quand ils contiennent une URL et vous donnent un sentiment d’urgence. Préférez passer directement par le site pour vous connecter et déjouer les tentatives de phishing.
  • Configurer correctement votre SSO en :
    • Whitelistant les paths de redirection en plus du nom de domaine
    • Autorisant uniquement le type que vous souhaitez sur votre flux, sur notre exemple c’était code
  • Corriger vos failles open redirect :
    • Valider que le domaine de la redirection vous appartient

🏹 Pour aller plus loin

Nous avons pour ambition de sécuriser le web, et pour atteindre cet objectif, nous avons besoin de vous ! Si vous avez des questions, des suggestions ou le moindre doute, n'hésitez pas à contacter notre équipe sécurité, par mail security@theodo.fr.

Topics: Sécurité