Facebook: multiples vulnérabilités au sein du réseau social

Failles XSS et CSRF critiques dans Facebook - le 05 octobre 2011


...ou comment deux failles sur Facebook permettaient de récupérer l’intégralité des données personnelles des utilisateurs mais également de modifier et de détruire leur profil. Facebook souffrait jusqu’à la semaine dernière d’une série de failles de type XSS et CSRF découvertes par notre équipe.
Situées pour la plupart sur les versions mobiles de Facebook (m.facebook.com et touch.facebook.com), ces failles pouvaient être utilisées pour lancer des attaques extrêmement dangereuses pour les données des utilisateurs. Nous avons élaboré un scénario au cours duquel un attaquant pouvait, au moyen d’une simple application Facebook, créer un véritable ver tirant partie de ces failles pour se propager et causer des dégâts importants sur les comptes des utilisateurs.
Dans le meilleur des cas, toutes les informations personnelles des utilisateurs étaient récupérées silencieusement sur un serveur externe. Dans le pire des cas, l’accès au compte était modifié par l’attaquant, et toutes les données personnelles du compte étaient entièrement détruites.

Introduction

Commençons par quelques chiffres sur Facebook : 500 millions de membres actifs de par le monde (17.2 millions en France), dont 50% se connectent au moins une fois par jour, 60 millions de changements de statut quotidien, 3 milliards de photos mises en ligne, 70 langues disponibles, plus de 500 000 applications disponibles...

De tels chiffres ont de quoi attirer les convoitises, et beaucoup d’esprits peu scrupuleux ont vite compris l’incroyable potentiel de ce réseau social. Ces derniers se rangent essentiellement en deux catégories : ceux qui exploitent les failles humaines en usant de la ruse et du mensonge (notamment à travers le phishing), et ceux qui exploitent les failles sécuritaires du réseau. Car Facebook n’est pas épargné par ce type de problème, et les nombreux patchs de sécurité appliqués durant ces trois dernières années sont là pour en attester. Néanmoins, à l’heure où Facebook vient de devenir le second site le plus visité au monde, on est en droit de se poser la question : les utilisateurs du réseau social peuvent-ils s’y promener en toute sécurité? C’est en tout cas la question que nous avions en tête au moment de nous lancer dans un rapide audit de Facebook cet été. Auditer un réseau social de cette taille est un travail de longue haleine, nous nous sommes cantonnés à en analyser l’essentiel, et cela a été bien suffisant. En voici les détails.


CSRF et XSS : les bases

Lors d’une attaque de type Cross-Site Request Forgery (abrégé en CSRF et prononcé “sea-surf”), l’attaquant tire partie du navigateur de la victime afin de lui faire exécuter des requêtes malicieuses sans son consentement, en général via des balises img ou iframe pointant vers des scripts effectuant des actions au profit de l’attaquant. Ce type d’attaque est encore relativement méconnu, et de nombreux sites ou logiciels web ne proposent aucune protection.

Les attaques de type Cross-Site Scripting (abrégé en XSS) sont, elles, largement plus répandues. Lors d’une attaque de ce type, l’attaquant parvient à injecter un script malicieux dans une page qui sera ensuite lue par la victime. On trouve classiquement ce type de faille sur des pages où une partie du contenu servi à l’utilisateur est généré dynamiquement à partir des données envoyées par l’utilisateur lui-même. Ce type de faille a longtemps été exploité uniquement pour voler les cookies d’identification des victimes afin de prendre possession de leur compte. Avec l’émergence des réseaux sociaux, les failles XSS prennent un nouvel envol, comme nous allons le voir. Si vous n’êtes pas familier avec les failles CSRF et/ou XSS, les bases précédentes sont reprises et illustrées dans les vidéos ci-dessous.


CSRF et XSS : les protections

Il existe pour les sites web un certain nombre de moyens de se protéger contre les attaques de type CSRF et XSS. Dans le cas CSRF, un nombre de plus en plus important de sites ont mis en place des systèmes de jetons accompagnant la plupart des requêtes effectuées par les utilisateurs. Ces jetons sont uniques pour chaque utilisateur, et sont en général impossibles à deviner par une personne tierce. Ils servent ainsi à vérifier la légitimité des requêtes, selon qu’elles incluent un jeton ou pas. C’est ce système que Facebook a choisi de mettre en place, et ce de manière double puisque les requêtes sont systématiquement (ou presque...) accompagnées de deux jetons anti-CSRF, ayant pour doux noms post_form_id (32 caractéres hexadécimaux) et fb_dtsg (5 caractères parmi [a-zA-Z0-9.-]).

En ce qui concerne les attaques XSS, il n’existe pas de parade universelle. La seule ayant partiellement fait ses preuves est l’ajout (au niveau navigateur) d’un marqueur appelé HttpOnly sur les cookies d’identifications, permettant d’empêcher le vol de ces derniers. Mais une attaque XSS peut se révéler bien plus complexe et destructrice qu’un simple vol de cookies, comme nous le verrons dans la dernière partie.


Présentation des failles

Commençons par les failles CSRF. La première faille n’est pas réellement de type CSRF, mais elle peut tout de même être considérée comme telle, vu qu’elle permet de récupérer le jeton post_form_id de n’importe quel utilisateur, connecté ou pas. Cette faille (ou plutôt bug?) se retrouve à deux endroits différents:

http://www.facebook.com/profile.php?v=wall&viewas=<viewer_id>

et

http://www.facebook.com/ajax/stream/profile.php?__a=1&profile_id=<user_id>&viewer_id=<victim_id>


Le premier script permet d’afficher le mur de l’utilisateur courant, mais il revêt une fonctionnalité supplémentaire lorsque le paramètre viewas est fourni. En effet, ce paramètre permet, lorsqu’il est suivi de l’id d’un utilisateur lambda, de voir comment son propre profil apparaît aux yeux de cet utilisateur lambda. Une bien belle fonctionnalité au demeurant, mais malheureusement entachée d’un bug très embêtant : lorsque l’utilisateur courant a permis (via ses paramètres de sécurité) à quiconque de commenter les posts de son mur, alors le jeton post_form_id de l’utilisateur lambda est fourni en cadeau dans le code source. L’équipe Facebook a décidément du mal avec cette fonctionnalité, déjà victime de bugs sécuritaires par le passé. En ce qui concerne le second script, le fonctionnement est quasiment identique : ce script fournit un fil d’actualités sur le profil de l’utilisateur défini par profile_id, tel que vu par viewer_id. Il suffit dès lors d’inscrire l’id de l’utilisateur courant dans profile_id et celui de la victime désignée dans viewer_id pour voir apparaître le jeton post_form_id de cette dernière, toujours sous la condition de permission d’écriture sur le mur de l’utilisateur courant. Intéressant direz-vous, mais quid du second jeton fb_dtsg? Malheureusement (ou heureusement?), il n’est pas possible de récupérer ce dernier par cette technique. Néanmoins, nous verrons que l’on peut parfois (au grand dam de l’utilisateur) se passer de ce second jeton...

La seconde faille CSRF peut, elle, sembler relativement anodine, voire même carrément inutile, mais il ne faut pas s’y fier. Celle-ci se situe sur la version mobile de Facebook (m.facebook.com) et concerne l’action “j’aime” si chère à nos amis facebookers. La faille est simple : l’url requise pour effectuer cette action ne nécessite aucun jeton anti-CSRF. Via une balise img ou iframe, un attaquant peut donc faire “aimer” par la victime un post quelconque sur un mur public (ou sur lequel la victime a des droits suffisants). Rien de bien palpitant à priori... sauf que ce faisant, le nom de la victime apparaît à côté du post tant aimé. Cette astuce peut donc se révéler extrêmement pratique si l’on veut déterminer l’identité de notre victime et ainsi récupérer son jeton post_form_id, comme détaillé dans la première vidéo.

En ce qui concerne les failles XSS, elles sont situées là aussi sur des sous-domaines de Facebook liés aux versions mobiles : m.facebook.com et son équivalent “tactile” touch.facebook.com. Ce sont en réalité deux versions quasiment identiques de la même faille, au niveau des scripts

http://m.facebook.com/l.php?u=<external adress>

et
http://touch.facebook.com/l_warn.php?u=<external adress>


Ces scripts ont pour fonction de rediriger l’utilisateur vers des liens externes, et ils sont en général appelés avec deux paramètres principaux : le paramètre u contenant l’url externe, et le paramètre h contenant un hash de vérification sur l’origine de la requête. Lorsque ce hash est omis, l’utilisateur tombe sur un message l’avertissant qu’il est sur le point de quitter Facebook pour l’url passée en argument. Or cette url est insérée dans le code source sans avoir été correctement filtrée, permettant ainsi l’injection de code dans la page. Ainsi, des urls telles que

http://m.facebook.com/l.php?u=http://www.exemple.com/<script>alert(document.location);</script>

ou
http://touch.facebook.com/l_warn.php?u=http://www.exemple.com/"<script>alert(document.location);</script>


généreront des alertes javascript, ouvrant dès lors la voie à des attaques XSS telles qu’expliquées dans la seconde vidéo.


Exploitation des failles : vol et destruction des données personnelles

A première vue, ces failles peuvent sembler anodines : un bug permettant de retrouver un seul des deux jetons anti-CSRF, une mini-faille CSRF à priori inintéressante et une faille XSS tout ce qu’il y a de plus classique. Pourtant, sous-estimer leur potentiel serait une grave erreur. Et c’est ce que nous avons décidé de montrer dans les vidéos ci-dessous, mettant en scène deux scénarios d’attaque où un attaquant parvient à créer un véritable ver, tirant partie des failles pour se propager et causer d’importants dégâts sur le compte de la victime. Dans le premier scénario, basé sur les failles CSRF, toutes les informations personnelles de la victime sont récupérées silencieusement. Dans le second scénario, exploitant les failles XSS, l’accès au compte est modifié par l’attaquant, et toutes les données personnelles du compte sont récupérées puis entièrement détruites. A noter que pour les deux scénarios, lorsqu’un utilisateur est infecté, il assure la propagation du “ver” en recommandant, sur son profil et par messagerie interne (pour la XSS), une application Facebook contrôlée par l’attaquant (voir plus bas). Ainsi on peut raisonnablement considérer que chaque personne infectée contamine au minimum 50% de ses amis: la propagation du ver est exponentielle. Et la collecte d’information personnelles par l’attaque l’est, de fait, également.

Dans ces deux scénarios, l’attaquant tire partie d’une possibilité très pratique offerte par Facebook : créer une application. Pratique car ouverte à n’importe quel utilisateur, mais aussi pratique de par son fonctionnement. En effet, lors de la visite d’un utilisateur sur la page d’une application Facebook (http://apps.facebook.com/wargan_app par exemple), l’url où se situe cette dernière est chargée via une iframe. Cela offre ainsi la possibilité pour un attaquant de charger malicieusement n’importe quelle page externe dans le navigateur de la victime à partir d’une url officielle de Facebook , et ce de manière transparente. La victime n’a ainsi aucune raison de se méfier, rendant l’attaque potentiellement très puissante.


Vidéos explicatives:





Conclusions et perspectives

Ces vidéos montrent de manière limpide à quel point des failles considérées comme bénignes la plupart du temps, peuvent se révéler extrêmement dangereuses dans le cadre des réseaux sociaux. Les scénarios présentés dans les vidéos restent cependant des attaques relativement simples, et il serait tout à fait possible d’élaborer des scénarios nettement plus complexes, visant à créer par exemple une armée de navigateur zombies ou un botnet social. Tout ceci pourrait être combiné avec des failles applicatives critiques dont on parle beaucoup aujourd’hui (PDF/Flash), et une simple faille XSS pourrait ainsi mettre à mal la sécurité de plusieurs millions d’ordinateurs.


Crédits

Ces vulnérabilités ont été découvertes par John Jean pour Wargan Solutions.

Contacter John JEAN (john at wargan dot com) -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.4.9 (GNU/Linux) mQGiBEo1REYRBADDGgkQVv+iN+LzRFH3WiDX+S0iTPg60MzTifYpfbeKH+FwdN/J /lujfR3TjielPEWVbYCnPJA/wHNNUACm6+qWoPx5SzjKq1BXMoGoUkO5DtXivboG NugVyKOBh7OARWilOkP6eB2zqbf/2ReHQtbX8a7xWyHzApyIAo/F2CiYOwCg7SyD UQifs08r8Um3pmyLMxTVjncD/1BrpfSWgYJYFLPobHuRvtoEyhK9ONuNWgQKYHQm mpoM6nxNVijySPpgyuyeDcyxgOzLJ3QI9Mqx+tmr1uLFZhAWSe0K5uz64pQ9PUMF LTvN5uN3sVAER4kA1Jxs5foTIkrCA6eQqmypIfo/egX1W1Y/1uC0aB0/kG11rQO0 fgUwA/4qubdS0PcnPZUQYVJUe6rDx5r2U/WVD+sHFY+ILFnVzdrxEdr1md35e9P5 ovuMfUunIwKH8BjSG3fXXESTZuZXfFlqwrR+m1y5qUcXwr9wnffRP2iQxIaQi5+b D4dR1J+oiNlPlVL8FuKK1dKHjIN9u4tjlE/VWCxoUyo97320z7QtSm9obiBKRUFO IChHZWVrIFdvcmthaG9saWMpIDxKb2huQHdhcmdhbi5jb20+iGAEExECACAFAko1 REYCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRBthXHBmOb+lvYJAJ9k30a7 lZx92PXQfNeoKocX5Uo3vACgtWuhqkDB1IvRMjMe49ng18Sp87y5Ag0ESjVERhAI AM0fzE0z5enz37lGPPHZrgW+XYWHNLfoR0gJvpu0FkPj4udPYL6+RJLGocWeJQBb UuEgcFdKJugxs3U9y/5iSFfM3e5+jOqPZCj6loP8nY9yarfVQHlZKqn6zseCT3D8 d1uTNJWnzb5LYnbFrETCyJbaENH8jzNQCGP3NCyIfXfn5Wag7HUh6Zi6njwl/2zx saizuQ3Wv0PjiVuJ8QEPvOdN9crTwt/JB2xRd98st7S5oEHvP96MyOtWSUWEnLSG fQhVyZC+aLLCOp8ggNkCAwOUGvPetJXVOLaPUJAoEwzDxXl43+GlKreqXH+W2GZT 0/n8W4p28Xrqv2G/SJa9sg8AAwUH/0GvW9eYRLaRDuAaBdlGX8jXsCnOvdMoioeg Wq9HwIYr94/kW2wJ1QFnhuEU/0cwx9MVrMElW0Q14kyY3KVUWAVpUTbfUPmtD6lo RO3EnoHDJoaak0yuw67Townpc9zRIBci3vUcUTh9SwUtv16b96DI92BRRu8XBaRU 13E33BWUkf6DebpYHmCmlwy3NelHfOtbzc2FBJ7Xt+hQnxd+07V2NgUNjMpCQrMD oh8ulOLWvrGKm7SZhV0ubqTt85mM6j5tmw0dkMwsGhgnf0U12uMfEKxm3IjcU+uk 0757WvPQQcr/iFSjxXwroqIgZpSJ/L1c8cfXgZ5bf0syeFODxEGISQQYEQIACQUC SjVERgIbDAAKCRBthXHBmOb+loxrAKDUB6CWC+kYIOaRmD9IvVfKosm9wgCeN4XV 3vIlH84xsRZ/rS/yfwggdDc= =jCPh -----END PGP PUBLIC KEY BLOCK-----