07
juin
'12

La difficile publication de vulnérabilité

Publié le 07 juin 2012

La philosophie du hacking implique une curiosité constante, et donc le fait que l'on mette notre nez un peu partout. C'est grâce à cela que des problèmes voire même des vulnérabilités sont identifiés, et résolus. Le problème, car il y a problème, réside dans la difficile communication et le fait que l'on fasse une très bonne cible en faisant part d'une trouvaille.

La curiosité est un vilain défaut

Tout le monde le sait. C'est pas bien. Mais il est des personnes qui ne peuvent s'empêcher de se poser des questions, légitimes ou non. Ce n'est pas (encore) une maladie, mais c'est ce qui motive certaines personnes. Dont moi. Et je dois avouer que la plupart du temps, c'est assez payant. Cette curiosité est le moteur essentiel de ce blog, de mes outils, etc ... Tout vient de questions que n'importe qui (enfin, je suppose que n'importe qui se les pose) pourrait se poser, et de la réflexion qui s'ensuit.

Malheureusement (sic), cette curiosité pousse des fois à tester ou vérifier des faits, à la limite de la légalité. Ce qui permet de cerner correctement un problème et de le reporter ou d'alerter. Et c'est lorsqu'on alerte, que l'on prévient, que les choses se corsent. Car dans certains cas de figure, la question d'où part une analyse ou une réflexion peut être considérée comme inopportune voire comme une action offensive. Alors qu'il s'agissait de pure curiosité, sans animosité aucune. Mais certaines personnes ne voient pas cela d'un bon œil, car le fait d'alerter ou de reporter peut nuire à leur image (ou celle de leur entreprise, ou administration) et je comprends tout à fait le besoin de se couvrir. Il est vrai qu'en France on a cette aversion naturelle contre les hackers (favorisée par les médias), et d'autant plus pour ceux qui publient des choses qui fâchent ou ennuient.

La nécessité de transparence ?

Il est évident que la publication, la diffusion, le fait d'alerter sur une vulnérabilité ou un problème identifié ne doit pas être fait n'importe comment. Certains préfèrent l'anonymat, et dévoilent à coup de pastebin des fuites d'informations, ou des vulnérabilités originales. S'ensuit généralement une tentative d'identification de la source, qui des fois aboutit après de fastidieuses recherches. Mais le fait de publier sous couvert d'anonymat vous place directement dans la mauvaise catégorie: pourquoi vous cachez-vous, si vous n'avez rien à vous reprocher ?

A contrario, beaucoup d'entre-nous pensent que la transparence est le meilleur atout. Nous nous permettons de publier des alertes, de reporter des problèmes ou des erreurs en toute bonne foi, sans nous cacher forcément derrière un pseudonyme (bien qu'on puisse en avoir un) et revendiquer la trouvaille. Si jamais quelqu'un est froissé, ou ennuyé par une publication, l'auteur de celle-ci est identifiable et joignable. De fait, annoncer sur Twitter ou par email sans masquer son identité est gage de sérieux, ou de grande folie. Malheureusement, lorsque les choses se gâtent, la seconde option est préférée.

Heuu ... à quand une prise de conscience ?

De suite, on tape sur la personne qui a identifié le problème. Vous annoncez sur Twitter que vous avez identifié une vulnérabilité dans un produit sans donner trop de détails ? Vous dévoilez un fichier planqué au fin fond du web et contenant des informations critiques ? Vous avez identifié un problème ou une anomalie et communiquez dessus au monde entier ? You're doing it wrong. Et même si l'envie vous prend de le transmettre par email, l'issue est globalement la même: l'annonceur est fautif. Victime de sa curiosité. Et peut-être de sa volonté d'alerter et de faire connaître sa trouvaille. On tire sur le messager, meme si je dois avouer que dans certains cas il n'est pas forcément tout blanc.

La problématique est ancienne: comment dévoiler une vulnérabilité/anomalie/faille en toute bonne foi, sans se cacher, et sans risquer les foudres des personnes concernées ? Quid du responsible disclosure ? C'est un débat qui dure, bien qu'en France il soit déjà plié, j'en ai bien peur. Par expérience, j'ai tendance à dire que lorsque l'on tente de dévoiler ou d'alerter, on devient une cible (que cela soit justifié ou non, là n'est pas la question). Certes, nous pronons le hacking "éthique", et cette volonté de transparence et de communication fait partie de cette éthique. Mais sincèrement, il est plus risqué de communiquer sur une vulnérabilité que de se taire et de la garder pour soi. Beaucoup en ont fait l'expérience: Guillermito [1], Damien Bancal [2] par exemple.

Alors, comment dévoiler/communiquer ?

Le constat est triste: soit on dévoile et on risque les sanctions prévues aux différents articles de la loi française (pour rappel, les articles 323-1 à 323-7 [3], avec des peines allant de 2 ans d'emprisonnement et 30 000€ d'amende à 5 ans d'emprisonnement et 75 000€ d'amende), bien que de bonne foi, soit on se tait et les choses ne bougent pas. J'avoue que cette vision est pessimiste, mais sincèrement je ne vois pas comment on pourrait éviter cela. Triste constat, disais-je.

Allons-nous devoir attendre que les responsables sécurité arrêtent de faire la sourde oreille et tentent de sauver leur place sans assumer les problèmes qui se posent ? Faut-il encore diaboliser Internet, l'informatique et le hacking en général, ainsi que les personnes compétentes en France ? L'ANSSI a ouvert la voie (du moins on ose le croire), en faisant appel à la culture hacker (il n'y a qu'à voir leur wallpaper `4]), en recrutant massivement et en le faisant savoir à différentes conférences sécurité prisées des hackers (non, pas de troll sur l'AN^W^WSSTIC). A qui le tour ?

Références

[1] [L'affaire Guillermito <http://guillermito2.net/archives/2004_12_28.html>`_

`2] [Damien Bancal (Zataz) vs le FTP anonyme <http://www.pcinpact.com/news/48753-zataz-faille-securite-trou-signalement.htm>`_

`3] [Code pénal, Livre III, Titre III, Chapitre III: Des atteintes aux systèmes de traitement automatisés de données <http://www.legifrance.gouv.fr/affichCode.do;jsessionid=DBA449F582FD48DF11068D44A409B79B.tpdjo07v_3?idSectionTA=LEGISCTA000006149839&cidTexte=LEGITEXT000006070719&dateTexte=20120510>`_

`4] [Wallpaper ANSSI <http://www.ssi.gouv.fr/IMG/png/wallpaper-anssi-2560x1920.png>`_

17
févr.
'12

Jiwa v3, retour à la case départ

Publié le 17 février 2012

Je suis retourné sur Jiwa aujourd'hui. Je m'attendais à trouver ma plateforme de musique habituelle, mais je me suis rendu compte que cela faisait un bail que je n'y avais pas été. Le site a complètement changé de look et a été repris par *Allomusic* qui en a profité pour le PURifier à l'Hadopi. Vu que je m'étais bien intéressé à cette plateforme il y a de cela quelques années, je me suis demandé si les choses avaient changé. Et puis parce que cette satanée limitation de 30 secondes d'écoute m'a été insupportable.

Jiwa version 3

Comme en témoigne le code source de Jiwa, le site est passé en vesion 3:

<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# jiwavtrois: http://ogp.me/ns/fb/jiwavtrois#">

Jiwa avait fait de nombreux efforts il y a quelques années pour empêcher le téléchargement des fichiers MP3 et leur sauvegarde. J'avais d'ailleurs à l'époque rédigé quelques articles et développé une extension Firefox dédiée. Il semble donc raisonnable de penser que les protections mises en place dans le code sont identiques ou meilleures que les dernières implémentées.

J'ai donc repris mes anciens Proof of Concept, et je me suis attelé à la tâche. J'ai tout simplement réessayé mes outils, sans succès. J'ai donc sorti l'artillerie lourde (paros + firefox) et commencé à regarder les requêtes et là, ce fut la surprise. Une grosse suprise. Non seulement quelques détails ont changé, certes très minimes, mais j'ai pu retrouver des requêtes similaires à celles employées quelques années plus tôt sur Jiwa ... Comme si on avait fait un bond en arrière de quelques années.

C'est reparti comme en 40 !

Autant dans la version précédente de Jiwa, on pouvait toujours écouter sans limite, autant avec la version actuelle Jiwa ne sert que d'appât: les pages redirigent pour l'écoute vers le site d'Allomusic, qui bride énormément les contenus et force un poil la main pour amener le visiteur à prendre un compte Premium.

Il faut dire qu'à l'époque où je m'étais interessé à Jiwa, l'écoute en ligne était toujours possible, ce qui par ailleurs me satisfaisait pleinement. Mais dans la configuration actuelle, je trouve ça un brin décevant de se servir de l'ancienne image de Jiwa pour essayer de remonter l'image d'un autre service.

On s'éloigne quand même du modèle original de Jiwa, et même de celui de Deezer: il ne s'agit plus de streaming gratuit en ligne reposant sur de la pub mais d'une version lite qui vise à convertir les utilisateurs en comptes Premium. Certainement une preuve que le modèle économique qui se veut reposer sur la pub n'est pas viable, comme a pu l'expérimenter Deezer. Sans parler des tarifs faramineux demandés par les majors comme Universal Music.

Alors bon, je ne suis pas un fervent adepte de ce système, bon nombre de lecteurs le savent, et j'ai adapté mes précédents scripts pour prendre en charge la version actuelle de Jiwa. Plusieurs restrictions ont été mises en œuvres pour éviter le téléchargement:

Le détail amusant c'est que même si l'écoute est limitée à 30 secondes, le fichier MP3 complet est téléchargé. Le bridage par user-agent est même complètement inefficace, je soupçonne même le script distant de bugger quasi aléatoirement ...

iJaw nouvelle génération

Pour ceux qui seraient intéressés, je diffuse ci-après le code source de mon Proof of Concept amélioré. Ce bout de code python est un poil sale, mais je ne compte pas le maintenir. C'est une preuve de concept, juste présente pour démontrer ce que j'affirme dans ce billet.

"""
Crapy Jiwa download tool
"""

import re
import sys
import json
import time
from hashlib import md5
from random import choice
import urllib,httplib,urllib2

def filter(s):
        return s.replace('\n',' ')

def randomUA():
        rstr = ''.join([choice('0123456789') for i in range(32)])
        return 'Mozilla Firefox (%s)'%rstr

def getSongDetails(sid):
        r = urllib2.Request('http://www.jiwa.fr/song/%d/play/'%sid)
        resp = urllib2.urlopen(r).read()
        return json.loads(resp)

def lookupSongs(keywords):
        try:
                r = urllib2.Request('http://www.jiwa.fr/search?q=%s'%urllib.quote(keywords))
                resp = urllib2.urlopen(r).read()
                matches = re.findall('/track/.*-([0-9]+)\.html',resp)
                res = []
                for match in list(set(matches))[:5]:
                        res.append(getSongDetails(int(match)))
                return res
        except urllib2.Error,e:
                return None


def dlTrack(sid,filename):
        errors = 0
        while errors<3:
                token = getToken(sid)
                _t = token.split('=')
                url = 'http://m.jiwa.fm/play.php'
                l1 = 'gwqd29ydg7sqys_qsh0'
                l3 = _t[0]
                l4 = _t[1]
                l5 = _t[2]
                l6 = _t[3]
                l7 = md5(l1).hexdigest()
                l8 = md5(l3+l7+str(sid)).hexdigest()
                url = "%s?r=%s&s=%s&t=%s&m=%s&from=1" % (url,l4,str(sid),l8,l6)

                r = httplib.HTTPConnection('m.jiwa.fm:80')
                r.putrequest('GET',url)
                r.putheader('Host','m.jiwa.fm:80')
                r.putheader('User-Agent',randomUA())
                r.endheaders()
                token = r.getresponse().read()
                if token=='-1':
                        errors += 1
                        time.sleep(1)
                else:
                        f = open(filename,'wb')
                        f.write(token)
                        f.close()
                        return True
        return False

def getToken(sid):
        params = *
        's':str(sid),
        *
        p = urllib.urlencode(params)

        r = httplib.HTTPConnection('m.jiwa.fm:80')
        r.putrequest('POST','http://m.jiwa.fm/token.php?r=1')
        r.putheader('Host','m.jiwa.fm:80')
        r.putheader('User-Agent',randomUA())
        r.putheader('Content-Type','application/x-www-form-urlencoded')
        r.putheader('Content-Length',str(len(p)))
        r.endheaders()
        r.send(p)

        token = r.getresponse().read()
        return token


if __name__ == '__main__':

        print '[>] iJaw - A Jiwa search & download tool'
        print '[>] author: virtualabs (http://www.virtualabs.fr)'
        print '[>]'

        if len(sys.argv)>2:
                operator = sys.argv[1]
                if operator == 'search':
                        kw = ' '.join(sys.argv[2:])
                        print '[+] Looking for songs ...'
                        tracks = lookupSongs(kw)
                        if tracks:
                                if len(tracks)>0:
                                        print ''
                                        print 'Song ID  - Song Name [Artist, Album]'
                                        print ''
                                        for t in tracks:
                                                print '%s - %s [%s, %s]' % (t['songId'],filter(t['songName']),filter(t['artistName']),filter(t['albumName']))
                                        print ''
                                        print '%d songs found' % len(tracks)
                                else:
                                        print '[!] No songs found.'
                        else:
                                print '[!] No songs found.'
                elif operator == 'get':
                        tracks = [t for t in sys.argv[2:]]
                        for sid in tracks:
                                print '[+] getting track info ...'
                                _track = getSongDetails(int(sid))
                                filename = '%s_%s_%s.mp3' % (_track['artistName'].replace(' ','_'),_track['albumName'].replace(' ','_'),_track['songName'].replace(' ','_'))
                                print '[+] downloading track ...'
                                if dlTrack(sid,filter(filename)):
                                        print '[i] saved to %s.' % filter(filename)
                                else:
                                        print '[!] Unable to download song.'
                elif operator == 'dl':
                        kw = ' '.join(sys.argv[2:])
                        tracks = lookupSongs(kw)
                        if tracks:
                                for t in tracks:
                                        _track = getSongDetails(t['songId'])
                                        filename = '%s_%s_%s.mp3' % (_track['artistName'].replace(' ','_'),_track['albumName'].replace(' ','_'),_track['songName'].replace(' ','_'))
                                        print '[+] downloading song "%s [%s]" ...' % (_track['songName'],_track['artistName'])
                                        if dlTrack(int(t['songId']),filter(filename)):
                                                print '[i] saved to %s.' % filter(filename)
                                        else:
                                                print '[!] Failed to download song: %s' % _track['songName']
                                print '[+] Done.'
                        else:
                                print '[!] No songs found'
        else:
                print '[i] usage: %s [search|get|dl] [second arg]'
                print '[i]'
                print '[i] + you can look for songs:'
                print '[i]'
                print '[i]  $ ijaw.py search Madonna like a virgin'
                print '[i]  $ 12345 - Like a virgin [Madonna, ...]'
                print '[i]'
                print '[i] + and download a given song with its ID:'
                print '[i]  $ ijaw.py get 12345'
                print '[i]'
                print '[i] + or download all tracks found:'
                print '[i]'
                print '[i]  $ ijaw.py dl Madonna like a virgin'
                print '[i]'
                print '[i] + Have phun !'

Conclusion

Il est étonnant que le passage de Jiwa sous la houlette d'Allomusic n'ait pas introduit un nouveau système plus fiable de lecture de musique en ligne, et il est franchement dommage qu'une plateforme labellisée PUR force autant la main de l'utilisateur vers les comptes payants, en tentant de promouvoir l'écoute gratuite mais très limitée. OK, le modèle économique basé sur les pubs n'est pas forcément viable, mais on est pas QUE des vaches à lait. A bon entendeur ...

09
janv.
'12

Des réseaux dans les réseaux

Publié le 09 janvier 2012

On nous tanne le mou depuis des années avec le piratage, l'HADOPI et les méchantes personnes adeptes du téléchargement de type pair à pair, ou P2P. C'est encore très présent de nos jours avec la volonté de l'HADOPI de filtrer les sites de streaming, ou de lutter encore et sans merci contre les (derniers) adeptes du P2P. Ou du moins ceux qui n'ont pas encore découvert MegaUpload & consors et les joies du téléchargement direct. Malheureusement, cette chasse aux sorcières est vaine et pousse les choses dans le mauvais sens.

Une chasse qui tourne court

Plusieurs serial-downloaders se sont fait attraper par la Haute Autorité, mais à ce jour aucun d'eux n'a été envoyé dans un tribunal. Il semble que le troisième volet de la riposte graduée ne soit pas encore très prisé par la HADOPI elle-même, comme le montre le cas de l'enseignant Thollot. Elle préfère le pédagogique au répressif, en conformité avec sa raison d'être.

La société mandatée par les ayants-droits et autorisée par l'HADOPI à collecter les adresses IP des pirates a montré ses faiblesses, révélées par Bluetouff, et l'interconnexion entre la Haute Autorité et cette société est toujours interrompue, bien que l'audit de sécurité mené par HSC ait été réalisé et le rapport remis.

A quelques semaines des élections, les programmes des candidats divergent, et certains parlent déjà de supprimer cette Haute Autorité qui ne sert à rien, si ce n'est à faire peser au dessus de la tête de Madame Michu une bonne vieille épée de Damoclès. "Attention, si tu télécharges, ca va couper !", comme disait notre ami Dédé.

Les artistes se meurent ... mais ne se rendent pas !

Alors oui, on va me dire que les artistes se meurent, et que la rémunération de la création n'est pas ce qu'elle devrait être. Pouvez-vous me dire ce que l'HADOPI a fait pour améliorer la rémunération de la création d'œuvres ? Hmm ? Pas grand chose,`aneffé <http://www.laquadrature.net/fr/hadopi-albanel-passe-son-oral-020>`_. Bon, je ne commenterai pas la bonne santé des cinémas français, ni le regain d'intérêt des spectateurs pour la 3D, ou encore les records battus par Intouchables ou Bienvenue chez les ch'tis. Le modèle de rémunération français est obsolète, qu'on se le dise. Plusieurs artistes ont démontré qu'ils pouvaient être rémunérés (et très bien rémunérés) pour leur travail en se passant d'intermédiaires, avec une interaction directe avec leur public, comme Radiohead ou encore Louis CK.

Et non, les intermédiaires ne sont pas morts, je suis sûr qu'il y a encore de la place pour des fans de marketing viral, des adeptes et accros à Twitter et Facebook, et des personnes à même de faire connaître des artistes par leur dimension sociale. Ces gens là ont un avenir dans le monde artistique. Tout comme les artistes eux-mêmes. L'heure de la dématérialisation a sonné le glas d'un système archaïque, et tend à être la norme d'une jeunesse qui a grandi avec YouTube, DailyMotion et iTunes.

Les acteurs du futur de la création ne sont pas ceux que l'on attend. Non, ce n'est pas aux fans de musiques, de groupes, de mouvements divers de pousser au changement; ce n'est pas non plus aux maisons de disques de sauter le pas, de tenter l'aventure numérique. Non. Ces changements, ces prises de risques, ce sont aux artistes de les faire, de les prendre. Les artistes sont le moteur de la création, ce sont eux qui créent et font vivre leurs œuvres. En n'acceptant pas un modèle figé et ancien, en utilisant les nouveaux modes de communication et de diffusion ils toucheront un plus large public, et bénéficieront de cela. Et s'il y a une chose dont je suis sûr, c'est que ce public saura le leur rendre. Comme je l'ai mentionné dans un précédent post: osez. C'est à vous de faire l'avenir de la création artistique, ne soyez pas attentistes. Okay, je pense que vous avez saisi mon propos.

Et les réseaux dans tout ça ?

Eh bien ce sont eux qui en pâtissent, car un des effets de la répression des téléchargements de contenus illicites via P2P est la migration d'une grande partie des pirates vers des solutions non-fliquées, comme le streaming ou le téléchargement direct (direct download, ou DDL), abusant ainsi du modèle client/serveur et générant un trafic monstre. Trafic tellement important, que plusieurs FAIs ont bien essayé de le limiter en douce. En fait, il s'agit d'un rétro-pédalage dans l'innovation technologique. Je m'explique.

Le système classique (qui a dit ancien ?) est basé sur un ou plusieurs clients demandant une ou plusieurs ressources à un serveur. On a donc un seul serveur qui dessert une certaine quantité de clients. Au delà d'un certain nombre de clients, le serveur reçoit trop de demande et ne peut toutes les satisfaire: il y a saturation (et ce brave serveur ne va pas s'en remettre de suite). L'avantage du système de téléchargement P2P, c'est que dès qu'un client a récupéré un bout d'une ressource, il la partage aux autres (et agit donc comme serveur à son tour), ce qui a pour conséquence d'augmenter l'offre tandis que la demande augmente, et donc de pouvoir assurer une très bonne disponibilité des ressources. Cela a aussi pour effet de répartir la charge sur l'ensemble du réseau, et d'éviter que le serveur ne soit un goulot d'étranglement. Ce principe d'échange est tellement efficace qu'il est désormais intégré de base dans plusieurs jeux pour réaliser les mises-à-jour, comme sur World of Warcraft (Blizzard) par exemple.

En condamnant la technologie P2P, on force plusieurs milliers (millions ?) de clients à revenir à l'ancien modèle, et à saturer de nouveaux les fournisseurs de ressources. Et forcément, la demande explose et le ou les serveurs ne suivent plus trop. Quand on pense qu'avec le P2P tout allait mieux ...

Un réseau dans le réseau dans le réseau dans le ...

Tout cela pour en arriver à ce dernier paragraphe, qui cette fois traite de bon sens. En criminalisant les personnes qui téléchargent des contenus soumis au droit d'auteur via des réseaux P2P ou même DDL, on les pousse à consommer du VPN à 5€/mois (un marché prometteur d'ailleurs), à utiliser bon nombre de moyens de chiffrement et d'anonymat, et à être paranoïaques. Non seulement les VPN*s et les moyens de chiffrement réduisent les performances, mais en plus ils créent un réseau dans le réseau. Cette tendance est d'ailleurs d'actualité, avec notamment `l'apparition et l'évolution des PirateBoxes <http://wiki.daviddarts.com/PirateBox_DIY>`_, ou encore l`es réseaux communautaires *Mesh <http://www.harakiwi.net/actualites/reseau-mesh-wifi-larme-absolue-anti-hadopi-2767.html>`_ voire même un réseau satellitaire communautaire et libre !

Il est très dommage de devoir réinventer la roue, et de se réapproprier des technologies et des moyens permettant d'échapper au contrôle et à la censure, encore plus de devoir créer un nouveau réseau libre au sein d'un réseau existant, comme le font ToR ou encore Freenet. N'était-ce pas la volonté même des créateurs de ce super-réseau qu'est Internet ? N'est-ce pas là un vecteur de Liberté, offert à tout un chacun ayant accès à l'Internet ? Oh wait ... il faut payer. Pourquoi perdre son temps à tenter de limiter, contrôler, un réseau en évolution et devenu essentiel à bon nombre de gens et de sociétés aujourd'hui ? Que seraient Facebook, Google, Microsoft sans Internet ?

Les initiatives de réseau communautaires sont louables, en ce sens qu'elles permettent un accès à un réseau gratuit avec des moyens modestes, bien que pour certaines un peu utopiques à mon goût. Mais le coup de la PirateBox, sorte de TAZ où l'on peut partager et échanger librement, j'avoue que je suis fan :).



Les contenus disponibles sur ce blog sont publiés sous licence Creative Commons BY-NC-SA.
Vous pouvez réutiliser tout ou partie de ces contenus à condition de citer l'auteur et l'origine, vous ne pouvez en faire une utilisation commerciale, et enfin vous devez partager tout travail ou œuvre dérivée sous les mêmes conditions — c'est-à-dire avec la même licence d'utilisation Creative Commons.