XSS dans Twitter pour IE <= 8

===================================

Français

For an english summary, go to the bottom of this post

===================================

Une mise à jour de Twitter a eu lieu pendant la nuit de mardi à mercredi, elle aura permis de protéger les utilisateurs d’Internet Explorer 8 d’au moins une faille XSS se trouvant dans la génération des tweets possédant des URLs contenant certaines séquences de caractères spéciaux.

En effet, lorsqu’on tweetait une URL contenant les caractères $_ (par exemple: http://www.example.com/a$_b), l’affichage du tweet partait en vrille en répliquant un certain nombre de fois l’URL et cassait les balises HTML prévues pour contenir le lien initial posté par l’utilisateur. Il faut savoir que Twitter utilise son “URL-shortener” (http://t.co) pour raccourcir les URL contenues dans un tweet et c’est dans le rendu du lien vers cette URL raccourcie que se trouvait le problème.

La réactivité de l’équipe sécurité de Twitter étant très bonne, je n’ai pas eu le temps d’analyser en détails la source de la vulnérabilité avant qu’elle ne soit patchée. Toujours est-il qu’une simple duplication du lien n’est que peu intéressante et j’ai alors cherché à faire exécuter du code par le biais de ce bug.

Pour cela, il fallait trouver un moyen de soit rajouter des balises HTML ou de profiter du fait que notre code se trouve déjà dans une balise pour y ajouter des event listener (type onload, onmouseover, …). La première solution s’est révélée impossible car les caractères < et > étaient correctement encodés. Par contre en ajoutant un guillemet (“) dans le texte du tweet, il était possible de sortir des champs prévus à cet effet et ajouter des champs à la balise HTML courante.

Afin d’exploiter complètement la faille pour obtenir une exécution de code, il fallait préparer un tweet avec un contenu similaire à celui ci-dessous.

"onmouseover=alert(1) http://www.test.com/a$_b test

Le moteur de rendu Javascript de twitter corrige par lui-même les espaces et guillemets manquants pour arriver au résultat ci-dessous. Le code est exécuté au moment où un utilisateur passe la souris au dessus de l’un des liens. Il faut savoir qu’à l’aide de styles CSS, il est possible de redimensionner le lien pour qu’il prenne toute la place et de ce fait l’utilisateur va forcément passer dessus.

N’importe qui visualisant ce tweet avec IE <= 8 (connecté à twitter ou pas) verrait le code exécuté dans son navigateur.

Après avoir découvert la faille, j’ai notifié l’équipe sécurité de Twitter (https://support.twitter.com/forms/security) avec les détails de l’attaque. Ils sont revenus vers moi moins de 10 minutes plus tard pour avoir des détails et la faille a été corrigée en moins de 12h. La mise à jour a permis d’homogénéiser le rendu des pages dans tous les navigateurs, corrigeant ainsi la faille qui n’affectait qu’Internet Explorer en version 8 ou moins.

===================================

English

===================================

A Cross-Site Scripting flaw affecting older versions of IE was discovered on Tuesday which could allow an attacker to take control of a user’s browser viewing a malicious tweet. The vulnerability was located within some of the rendering Javascript for IE versions 8 and lower.

When displaying a tweet with a link containing the characters “$_”, the rendering algorithm would repeat the link multiple times and by doing so, broke the HTML display of the tweet. By analyzing the flaw, it was possible to infer a way to execute code within the context of an infected page by abusing event listeners.

In the end, a tweet containing the following text could allow an attacker to control a victim’s browser.

"onmouseover=alert(1) http://www.example.com/a$_b test

The resulting display is showed below.

Twitter’s security team reacted very quickly when I notified them of the flaw and patched the site within a few hours of discovering the vulnerability.

DNS Rebinding + Java

Les découvertes de Stefano Di Paola sur les problèmes liés à la gestion des DNS de Java sont fort intéressantes. On va donc regarder ici pourquoi il est important de mettre à jour votre version de Java au plus vite.

Pour ceux qui ne le sauraient pas, le DNS Rebinding est une attaque dont l’idée est de forcer un client à effectuer plusieurs requêtes DNS vers un seul et unique nom de domaine et de répondre de manière différente pour chacune des requêtes. Ceci peut par exemple être utilisé pour contourner la “Same Origin Policy” (SOP) implémentée par les navigateurs Webs empêchant un site X de communiquer avec un site Y sur un autre domaine. En effet, si une page se trouvant sur le site X inclut une frame du site Y, il sera impossible d’accéder au contenu de cette frame depuis la page extérieure. Par contre, si l’attaquant arrive à faire croire au navigateur que la frame interne se trouve sur le même domaine que le site X, alors l’accès est autorisé.

Cette attaque reste cependant peu pratique car les navigateurs implémentent tous une protection contre le DNS Rebinding qu’on appelle généralement DNS Pinning, c’est-à-dire qu’ils vont garder en cache, pendant un temps plus ou moins long, la valeur de la réponse DNS, même si cette dernière contient un TTL de 0. Un attaquant est alors obligé de garder une victime sur un site malicieux pendant assez de temps (5 minutes sur Firefox par exemple) pour que l’attaque puisse avoir lieu.

Un exemple d’attaque pourrait être le suivant:

  1. L’attaquant convainc une victime de visiter le site http://evil.com
  2. Ne connaissant pas l’adresse IP de ce site, le navigateur effectue une requête DNS pour evil.com
  3. La réponse contient la réelle adresse : 6.6.6.6
  4. Le site charge un jeu en flash destiné à garder l’utilisateur sur la page aussi longtemps que possible
  5. Quelques minutes plus tard un JavaScript se lance pour accéder au contenu de la page http://evil.com
  6. Le cache DNS ayant expiré, le navigateur effectue une nouvelle requête DNS
  7. La réponse cette fois est de 192.168.1.1
  8. Le site peut alors intéragir avec cette nouvelle adresse IP

On peut donc utiliser cela pour accéder à des ressources sur le réseau interne de la victime, ou accéder aux données de la victime sur un autre site où il se serait identifié au préalable.

Avec Java, l’attaque devient beaucoup plus rapide. En effet, à cause d’un problème d’implémentation, il est possible de réaliser l’attaque et de rebinder le DNS en quelques secondes. Lors du chargement d’une page d’un site X, la première requête DNS est effectuée pour accéder tout d’abord à la page, puis la JVM effectue immédiatement une deuxième requête pour accéder à l’applet. Cependant, si l’on modifie la réponse de cette réponse DNS, l’applet ne peut pas se charger, car il ne se trouve plus à la bonne adresse IP. Ceci n’est pourtant pas un problème, car il suffit de charger une deuxième applet sur un site aléatoire, pour ensuite pouvoir accéder aux commandes Java depuis Javascript tout en ayant garder en cache la réponse de la dexième requête DNS. L’attaque se décompose donc comme suit:

  1. Chargement de la page http://evil.com (DNS => 6.6.6.6)
  2. Chargement de l’applet par la JVM http://evil.com/applet.class (DNS => 192.168.1.1)
  3. Chargement d’une applet sur un autre site pour démarrer correctement la JVM
  4. Appels Java depuis Javascript
  • t = new Packages.java.net.URL(“http://evil.com/”);
  • u = t.openConnection();
  • in1 = new java.io.BufferedReader(new java.io.InputStreamReader(u.getInputStream()));

Ceci peut être fait en quelques secondes ce qui rend l’attaque beaucoup plus dangereuse.

Un deuxième aspect intéressant au niveau de Java est le fait qu’il ne gère pas le SOP de la même manière que les navigateurs Web. En effet, pour Java des requêtes entre plusieurs domaines différents se trouvant sur une seule et même adresse IP sont tout à fait valables. Il est donc possible de charger un applet sur le site X et accéder au contenu du site Y pour autant qu’ils soient hébergés sur la même machine.

Ceci pose évidemment un gros risque pour tout site se trouvant sur un serveur mutualisé. Mais en combinant cette “fonctionnalité” avec l’attaque par rebinding décrite plus haut, il est possible de créer des vecteurs d’attaques intéressants. Une idée décrite par Di Paola consiste à rebinder un nom de domaine à l’adresse 127.0.0.1. A première vue, cela ne semble pas extrèmement intéressant, mais cela permet par exemple d’ouvrir un port en écoute sur cette interface sur la machine d’une victime. Il est par contre impossible de s’y connecter depuis l’extérieur. Cependant, il est possible de demander au navigateur de s’y connecter en ajoutant une nouvelle frame par exemple. On peut à nouveau se demander quelle pourrait être l’utilité de cette manipulation jusqu’à ce qu’on se rende compte que plusieurs sites Web connus ont un sous-domaine qui résout en 127.0.0.1 et que souvent les cookies d’un site sont attribués pour le domaine ainsi que tous ses sous-domaines. Il est donc possible de voler les cookies de ces sites sans jamais sortir de la “sandbox” imposée par Java. Si l’on récapitule l’attaque, on note les points suivants:

  1. Victime se connecte sur le site X qui est résolu un 1.2.3.4
  2. Chargement de l’applet qui résout le site X en 127.0.0.1
  3. Applet ouvre le port 8000 en écoute sur 127.0.0.1
  4. Le site X dirige une frame cachée vers localhost.victimdomain.com (qui résout en 127.0.0.1)
  5. Le navigateur se connecte à localhost.victimdomain.com et envoie les éventuels cookies pour ce site
  6. L’applet reçoit la connexion ainsi que la valeur des cookies de la victime

L’exemple utilisé par  Di Paola est valable pour le site delicious.com dont localhost.delicious.com résout sur 127.0.0.1.

Ces attaques ne requièrent qu’une simple visite d’une page sous le contrôle de l’attaquant et ne nécessitent que quelques secondes. Il est donc fortement recommandé de mettre à jour votre version de Java au plus vite, si ce n’est déjà fait.

t = new Packages.java.net.URL(“http://lol.t.scrt.ch/”);
u = t.openConnection();

Clicklogin?

Beaucoup d’attaques plus ou moins récentes profitent du fait que les utilisateurs ont tendance à rester connectés sur beaucoup de sites simultanément. Ceci est en effet facilité par le fait que tous les navigateurs récents supportent le concept de “tabs” ou d’onglets. On peut par exemple mentionner le CSRF, souvent sous-estimé et mal compris, ou le clickjacking qui profitent du fait que le navigateur de l’utilisateur est authentifié à un site vulnérable pour y effectuer des commandes malicieuses. C’est pourquoi beaucoup de sites sensibles recommandent de fermer tous les autres volets de navigation avant de s’y authentifier.

Il semble alors évident que pour un attaquant, il y a un intérêt non nul à forcer une victime à se connecter à un site vulnérable avant d’attaquer son compte. Ceci peut être fait en abusant de la fonctionnalité des navigateurs leur permettant de garder en mémoire les identifiants de l’utilisateur sur différents sites.

En effet, un attaquant peut préparer une page malicieuse incluant une frame cachée du site à attaquer. Le navigateur remplit alors automatiquement les champs de login et de mot de passe. Il suffit ensuite de convaincre l’utilisateur de cliquer quelque part pour authentifier la victime sur le site à attaquer en repositionnant la frame sous son curseur. Dès lors, les traditionelles attaques de CSRF ou Clickjacking peuvent prendre place.

L’attaque fonctionne bien sur Firefox et Chrome, mais pas sur Internet Explorer, qui ne remplit pas automatiquement les champs enregistrés lors du chargement d’une page. Il serait intéressant de pouvoir demander au navigateur de ne pas remplir les champs lorsqu’ils ne se trouvent pas sur la page principale, mais dans une frame, d’autant plus si cette dernière est invisible.

L’importance de définir un but à un test d’intrusion

La valeur ajoutée d’un test d’intrusion, si on le compare à un simple scan de vulnérabilités, est le fait de mettre les résultats obtenus dans un contexte spécifique permettant de déterminer les vrais risques encourus par une société à cause d’une certaine vulnérabilité. Par exemple, un scanner automatisé ne sera pas en mesure de différencier l’impact d’une injection SQL sur un serveur Web hébergé chez un fournisseur externe ne contenant aucune donnée sensible et une injection SQL sur un site dont la base de données est hébergée sur le réseau interne et dont la compromission aboutirait à un accès distant sur le réseau privé de l’entreprise.

Il est donc évident que le contexte dans lequel une faille est découverte est important. Le pentester peut alors utiliser son expérience pour déterminer la criticité de cette dernière. Mais souvent cela ne suffit pas à donner une réelle idée du risque encouru par la société. En effet, en tant que pentester, il n’est pas toujours facile d’identifier quels sont les actifs critiques d’une société. Est-ce que le vol du contenu d’un site d’e-banking a le même impact que sur un site journalistique? La réponse semble évidente, du fait que la plupart des informations sur le deuxième site est de toute façon accessible à tout le monde. Mais dans la plupart des cas, la réponse n’est pas aussi simple et il est toujours embêtant de passer du temps à exploiter une faille pour récupérer des données pour se rendre compte au final qu’elles n’ont aucune réelle valeur pour le client.

Afin d’éviter ce type de problème, il est très important de définir un ou plusieurs buts lors du démarage d’un test d’intrusion. Un simple “piratez notre réseau” ne suffit pas. Afin que le test soit réussi et surtout utile pour un client, il faut tout d’abord déterminer avec lui quels sont les vrais risques liés à une attaque informatique pour l’entreprise. Quelle information doit être protégée à tout prix? Cela permet alors aux pentesters de cibler plus précisément leurs attaques et au final de pouvoir présenter des résultats pertinents qui peuvent être utilisés pour améliorer le niveau de sécurité.

On peut par exemple imaginer quelques buts tels que les suivants:

  • Accéder à distance au réseau interne
    • Par des attaques techniques
    • Par du social engineering
  • Compromettre un compte administrateur de l’application X en partant d’un compte lambda
  • Devenir administrateur du domaine depuis un poste client

Certains de ces buts peuvent paraitre évidents et certains diront qu’il s’agit du but de tout test d’intrusion, mais ce n’est pas toujours le cas, d’où l’importance de définir à l’avance les buts du test en collaboration avec le client. Cela lui permettra d’exploiter de la meilleure manière les résultats du test.

Abuser le filtre XSS pour faciliter une attaque de ClickJacking

Le clickjacking est une attaque relativement répandue visant les utilisateurs d’un site vulnérable X. L’idée est de faire cliquer l’utilisateur sur un endroit du site en question sans qu’il ne s’en rende compte. Le plus souvent, cela est fait en utilisant une iframe cachée sous la souris de l’utilisateur.

[sourcecode language=”html”]<iframe src="http://vulnerable.com" style="position:absolute; opacity:0"></iframe>[/sourcecode]

Afin de contrer cette attaque, beaucoup de sites utilisent des scripts dits de framebusting permettant à une page de ne pas s’afficher si elle détecte qu’elle est à l’intérieure d’une frame.

Le problème le plus évident de ces scripts est que si l’utilisateur a désactivé javascript, la page est tout de même affichée. En partant de ce principe, il est possible d’abuser le filtre XSS d’Internet Explorer 8 par exemple pour le convaincre que le script de framebusting est en fait une attaque XSS. Ceci aura pour conséquence de désactiver le script et de permettre l’attaque de ClickJacking. Typiquement il suffit de créer l’iframe de la manière suivante.

[sourcecode language=”javascript”]<iframe src="http://vulnerable.com/?toto=<script>/*code_frame_busting*/</script>" style="position:absolute; opacity:0"></iframe>[/sourcecode]

Le navigateur détectera alors le code comme étant du XSS et ne l’exécutera pas, ce qui veut dire que la page s’affichera normalement dans la frame.

La méthode la plus efficace pour bloquer le ClickJacking est l’utilisation du header HTTP X-FRAME-OPTIONS qui permet à une page de spécifier par quels autres domaines elle peut être “framée”.

Pour plus d’informations, vous pouvez lire l’article suivant qui contient pas mal de détails sur les différentes techniques de framebusting et de contournement.

http://seclab.stanford.edu/websec/framebusting/framebust.pdf