Logo Blog perso d'Ozwald

Brèves du jour

Par Oz le - Geek
I.A. Outil Réseau python scripts

Un mini billet pour deux petites brèves : une astuce python (déjà bien connue, mais plus on réplique ce genre d'info moins on a de mal à la retrouver quand on l'a oublié), et un pointeur sur un jouet sympa.

Tools - Creative Common by mtneer_man on Flickr

Tout d'abord l'astuce python : comment changer son user-agent quand on utilise la librairie urllib. C'est un problème ultra-classique puisque pas mal de sites font du filtrage sur ce user-agent et refusent de répondre quand ils repèrent un script python1. En fouillant sur le net on trouve pleins de méthodes plus ou moins bidons (certaines se contentent carrément de rajouter un second header "user-agent", ce qui n'est évidemment pas ce que l'on cherche à faire), et après en avoir testé au moins une demi-douzaine voici celle que j'utilise à présent (et qui marche :D) :

import urllib
# ============ USER AGENT MAGIC ===========
class UAOpener(urllib.FancyURLopener):
        version = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11'
urllib._urlopener = UAOpener()
# =========================================

Et voilà :) Comme pour le passage via TOR c'est tout ce qu'il y a à faire. Accessoirement j'ai réalisé récemment que le dernier paramètre de "setdefaultproxy" que j'utilise pour passer par TOR souffre un bug ennuyeux : il est ignoré :-D Donc que vous mettiez à "True" ou à "False" les résolutions DNS ne passeront JAMAIS par votre proxy socks (et donc par TOR)...ennuyeux n'est-ce-pas ? En tout cas maintenant vous êtes prévenus :)

Le petit jouet maintenant : ça n'a rien de nouveau non plus, mais c'est tout de même un jouet rigolo. Il s'agit du WOrdnet Libre du Français2. Pour ceux qui connaissent Wordnet : c'est Wordnet pour le Français ;) Pour ceux qui ignorent ce qu'est Wordnet c'est une base de donnée concernant le sens des mots et leurs relations les uns avec les autres. Un usage immédiat de Wordnet c'est de trouver des synonymes (dans la langue française avec WOLF, dans la langue anglaise avec le Wordnet original), un autre usage consiste à mesurer la proximité de sens entre deux mots par exemple. Les possibilités sont vraiment nombreuses, notamment en data-mining. Bref vous pouvez le télécharger ici au format XML, et ces trois mini remarques pourraient vous êtes utiles si vous voulez travailler avec :

  • Le document ne contient pas de balise racine, ajoutez donc en une si vous voulez que xmllint --format ou xml.dom.minidom.Parse ne vous insulte pas. Par exemple un petit <wolf> en début de document et un petit </wolf> en fin de document feront parfaitement l'affaire.
  • Les & ont tendance à faire crier le module python xml.dom.minidom. Pour ma part je les ai donc purement et simplement supprimés grâce à un petit sed.
  • Le XML pèse 38Mo sur disque, une fois parsé par xml.dom.minidom mon interpréteur Python prend plus de 1Go ;-) Veillez donc à avoir de la RAM disponible.

Gorgonite le 2011/10/22 13:45

MiniDOM... tu cherches aussi les ennuis pour traiter une telle quantité de données :p

  1. Par exemple wikipedia.
  2. WOLF

Petite visite du guérisseur

Par Oz le - Geek
Hack Réseau android python

Monsieur Soleil peut tout faire. Retour de l'être aimé, prédiction des résultats du loto, choix infaillible de la couleur de la cravatte, conjuration des problèmes d'impuissance, etc... Bon plus sérieusement je ne vais pas parler de ce type de guérisseur là, rassurez-vous. Je vais vous parler de Jason, figure de la mythologie grecque connu sous le surnom "le guérisseur"...bon non plus, ça c'était juste pour le jeu de mot (bien pourri). En fait je vais vous parler de JSON et, plus précisément, des JSON-RPC que j'ai eu la surprise de découvrir accessibles sur mon serveur...

Marabout - Based on a Creative Common photo published by "Ludovic Hirlimann" on Flickr

Pour poser le cadre donc : j'ai un serveur multimédia (allumé H241, comme tout bon serveur qui se respecte) et l'autre jour alors que je faisais le petit nmap routinier de mon réseau local apparait une nouveauté sur ce serveur :

PORT     STATE SERVICE     VERSION
9090/tcp open  zeus-admin?

Autant vous dire que, sur le moment, j'ai un peu fait la gueule :-D Après enquête rapide il s'avère que c'est en fait le XBMC qui tourne sur mon serveur qui expose là l'une de ses nouvelles interfaces de commande... Dans les anciennes versions, XBMC exposait uniquement (pour autant que je sache) une interface de commande HTTP accessible après authentification et qui permettait ainsi de controller les lectures multimédia via le réseau (super pratique pour transformer votre téléphone android en télécommande wifi). Dans les dernières version l'interface HTTP est deprecated, et c'est l'interface JSON-RPC qui devrait la remplacer.

Pour ceux qui l'ignorent (comme moi il y a quelques semaines), le JSON-RPC c'est une méthode de RPC qui utilise la syntaxe JSON (on ne s'en douterai pas hein ?). Et pour la conclure l'explication : le JSON c'est une méthode de formatage de données dont l'esprit est de se rapprocher de la syntaxe....javascript. Je ne plaisante pas, JSON c'est même l'acronyme de "JavaScript Object Notation" si vous voulez tout savoir. Du coup une requête JSON-RPC ça ressemble à ça :

{"jsonrpc": "2.0", "method": "subtract", "params": {42, 23}, "id": 1}

Bon...c'est pas très joli mais ça reste compréhensible :) Du coup je me suis dit "voyons ce que l'on peut faire avec ça", mais avant d'exposer les résultats je dois faire un disclaimer : "j'ai peut-être été trop permissif dans ma configuration d'xbmc (même si j'en doute), donc ne blamons pas trop les réglages qu'on peut/doit faire pour utiliser une télécommande, c'est peut être ma faute". Maintenant répondons à "que peut on faire avec ça ?" :

Première chose : survoler la liste des procédures accessibles. La première qui a une tête sympa c'est "JSONRPC.Ping". Aussitôt identifiée aussitôt testée :

echo '{"jsonrpc": "2.0", "method": "JSONRPC.Ping", "id":"5"}' | nc serveurmultimedia 9090

Et réponse immédiate :

{
   "id" : "5",
   "jsonrpc" : "2.0",
   "result" : "pong"
}

Cool ça marche :-D !!!...Pas cool : j'ai pas eu besoin de m'identifier :-/

La paranoïa aidant la seconde procédure que je teste c'est "Files.GetDirectory"...forcément.

echo '{"jsonrpc": "2.0", "method": "Files.GetDirectory", "id":"peur", "params":{"directory":"/"}}' | nc serveurmultimedia 9090

Ah bah....ça marche :

{
   "id" : "peur",
   "jsonrpc" : "2.0",
   "result" : {
      "directories" : [
         {
            "fanart" : "special://masterprofile/Thumbnails/Video/Fanart/cfb24076.tbn",
            "file" : "/var/",
            "label" : "var"
         },
         {
            "fanart" : "special://masterprofile/Thumbnails/Video/Fanart/b1fe6366.tbn",
            "file" : "/usr/",
            "label" : "usr"
         },
         {
            "fanart" : "special://masterprofile/Thumbnails/Video/Fanart/dafd2084.tbn",
            "file" : "/tmp/",
...ETC...

Et vous savez le mieux ? Y'a une procédure Files.Download :-D !...Après l'avoir testé dans tout les sens il semblerait qu'en fait cette procédure ne soit, pour l'instant, pas implémentée (ouf !) et que de toute façon elle ne permette de télécharger que des ressources générées par XBMC (vignettes, etc.). M'enfin déjà le simple Files.GetDirectory c'est pas très joli2...Du coup une seule chose à dire : faites attentions aux permissions que vous mettez sur votre XBMC si vous voulez utiliser une télécommande réseau, il se peut que vous ouvriez des portes à n'importe qui ayant accès au port TCP.

Ceci étant dit, on va considérer que ça cloture la partie "sécu" de ce billet, et on va voir si on peut jouer avec ça sans vilaines pensées, par exemple essayons de faire les requêtes en python :

>>> import json, socket, random
>>> req = {'jsonrpc':'2.0', 'id':str(random.randint(0,100)), 'method':'JSONRPC.Ping'}
>>> s =  socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> s.connect(("serveurmultimedia",9090))
>>> s.send(json.dumps(req))
>>> reponse = s.recv(1024)
>>> print reponse
{
   "id" : "82",
   "jsonrpc" : "2.0",
   "result" : "pong"
}

Intéressant...Du coup si jamais un script python sur android qui est en train d'exécuter time.sleep() ne consomme pas de CPU (donc de batterie) je pourrai m'écrire un script, utilisable sur mon téléphone, qui me réveille à l'heure de mon choix en jouant le média de mon choix sur mon serveur !!! Intéressant non ?

Pour que ça soit intéressant j'ai envie de lire un mp3 aléatoire. La logique de XBMC étant ce qu'elle est3 je dois d'abord récupérer les "sources" de music :

>>> req = {'jsonrpc':'2.0', 'id':str(random.randint(0,100))}
>>> req['method'] = "Files.GetSources"
>>> req['params'] = {'media':'Music'}
>>> s.send(json.dumps(req))
>>> reponse = s.recv(10*1024)
>>> shares = json.loads(reponse)['result']['shares']
>>> for s in shares:
>>>    print s['file']
/mnt/raid0/musiquelegalementachetee/
...

Une fois les sources récupérées (et surtout les répertoires associées, dans l'attribu bien nommé "file"...) on peut utiliser Files.GetDirectory dont on parlait plus haut afin de récupérer l'ensemble des morceaux directement à la racine de notre source (j'ai la flemme de coder le récursif pour l'instant) :

>>> req = {'jsonrpc':'2.0', 'id':str(random.randint(0,100))}
>>> req['method'] = "Files.GetDirectory"
>>> req['params'] = {'directory':shares[0]['file']}
>>> s.send(json.dumps(req))
>>> reponse = s.recv(100*1024)
>>> musics = json.loads(reponse)
>>> random.shuffle(musics['result']['files'])
>>> musique = musics['result']['files'][0]["file"]
>>> print musique
/mnt/raid0/musiquelegalementachetee/rickroll.mp3

Maintenant j'aurai adoré utilisé AudioPlaylist.Insert pour insérer la chanson à l'endroit de mon choix dans la playlist courante puis en lancer la lecture, sauf que quand je fais appel à AudioPlaylist.Insert j'ai une réponse Method not found....On va donc supposer que ce n'est pas encore implémenté :-( Résultat il ne me reste plus qu'à me rabattre sur AudioPlaylist.Add puis prier le guérisseur pour que lors de l'appel à AudioPlaylist.Play ce soit le bon morceau qui soit joué...Je l'ai donc fait :

>>> req = {'jsonrpc':'2.0', 'id':str(random.randint(0,100))}
>>> req['method'] = "AudioPlaylist.Add"
>>> req['params'] = {"item": {"file":musique}}
>>> s.send(json.dumps(req))
>>> reponse = s.recv(1024)
>>> print reponse
{
   "id" : "2",
   "jsonrpc" : "2.0",
   "result" : "OK"
}
>>> req = {'jsonrpc':'2.0', 'id':str(random.randint(0,100))}
>>> req['method'] = "AudioPlaylist.Play"
>>> s.send(json.dumps(req))

Et là ça ne joue pas le bon morceau :-S ... Vérification de la playlist : mon morceau n'a même pas été ajouté en fait... Heureusement la communauté des dev de XBMC est plutôt très active et j'ai rapidement trouvé le problème :

The current playlist implementation/representation in json rpc has many (design) flaws and there are lots of unsupported things and it will hopefully be completely rewritten for the next release (if there's enough time). Until then it might be the safest approach not to use the Playlist methods (except SkipPrevious, SkipNext, GetItems, Clear, Shuffle and UnShuffle which should work as expected).

We're sorry for the inconvenience and hope to provide a much better solution in the next version

Donc voilà : actuellement il est impossible de faire ce que je voulais :-( ..Snif. La suite peut-être à un prochain numéro :) !

  1. Que les amis de la planète se rassurent : c'est une machine à base d'atom qui consomme moins en H24 qu'une seule heure de jeu sur les dernières cartes graphiques à la mode
  2. Même si, comme moi, vous faites tourner votre XBMC avec des droits minimalistes
  3. et comme je n'utilise pas les fonctionnalitées "library" d'XBMC

Joyeuses Fêtes !

Par Oz le - Geek
Malware Réseau virus

Mini billet pour souhaiter de bonnes fêtes à tout le monde et, puisque c'est de circonstance, je vous résume1 la description faite sur VX Heaven du premier virus répandue à grande échelle sur un réseau informatique et en ayant notablement perturbé le fonctionnement : CHRISTMAS EXEC

Santa Claus - Creative Common by "kevindooley" on Flickr

CHRISTMAS EXEC a été écrit en 1987 (22 ans déjà...) par un étudiant de l'université de Clausthal-Zellerfield (Allemagne) dans le but de souhaiter un joyeux Noël à ses amis de l'université. A l'époque Internet tel qu'on le connait aujourd'hui n'existait pas, et le programme s'est donc répandu d'abord sur le réseau de l'université de Clausthal-Zellerfield (à mes souhaits), puis il a fuit sur le réseau de recherche européen EARNet, il a poursuivi sa folle épopée sur BitNet aux USA et a terminé sa course en paralysant VNet, un réseau privé utilisé par IBM pour communiquer avec ses fournisseurs et clients.

Rien de bien sorcier dans ce programme pourtant puisqu'il se contentait d'afficher un ascii-art de Noël ...et de s'envoyer par mail à tout les contacts qu'il trouvait sur l'ordinateur "infecté". Les guillemets autour de "infecté" sont d'ailleurs importants puisque pour s'exécuter le programme avait besoin d'être volontairement lancé par l'utilisateur (bah ouais, de la bonne vieille ingénierie sociale :) ).

Comme quoi on n'a rien inventé...et 22 ans après on trouve encore des gens capable d'exécuter n'importe quoi quand on leur demande (je pense en particulier aux codecs "indispensables" pour visionner des films interdit aux moins de 18 ans, ou encore aux super antivirus-de-la-mort-qui-tue et qui doivent absolument être installés parce qu'ils viennent d'identifier 352 infections différentes sur votre poste mais qu'ils peuvent vous aider à le nettoyer...)

Allez, pour conclure ce billet (et certainement l'année vu que je pars loin du net pour la fin du mois) je vous retranscrit l'ascii-art de CHRISTMAS EXEC, ça n'a pas vieillit d'un poil :) !

                    *
                    *
                   ***
                  *****
                 *******
                *********
              *************                A
                 *******
               ***********                VERY
             ***************
           *******************            HAPPY
               ***********
             ***************            CHRISTMAS
           *******************
         ***********************         AND MY
             ***************
           *******************         BEST WISHES
         ***********************
       ***************************     FOR THE NEXT
                 ******
                 ******                    YEAR
                 ******
  1. et je traduit également, si ça c'est pas trop gentil de ma part ?!
  2. Remplacez vous même par 10D6 pour le résultat correspondant à votre ordinateur

Du python à l'oignon

Par Oz le - Geek
Réseau TOR python

Parmi les jeunes langages de scripts à la mode de nos jours on distingue assez clairement deux leaders : le python et le ruby. Le nombre de trolls velus entre ces deux langages est d'ailleurs assez impressionnant ! Personnellement j'utilise le python puisqu'il répond à tout ce que j'attend de la part d'un langage de script (je ne prétend donc pas qu'il soit mieux ou moins bien que le ruby que je n'ai juste pas testé), et quand par hasard une fonctions que j'aurai aimée n'est pas présente de base il est souvent enfantin de la rajouter comme je me propose de vous en donner un exemple dans ce billet !

Oignons - Creative Common from "ILoveButter" on Flickr

L'une des bibliothèques standards du python que j'ai apprécié le plus vite c'est la bibliothèque "urllib"1 qui permet, entre autres choses, de récupérer une page web en une toute petite ligne de code :

urllib.urlopen("http://www.ozwald.fr").read()

Quand on compare aux dizaines de lignes nécessaires en C pour obtenir la même chose, ça donne des frissons de bonheur ! Avec cette librairie tout ce que l'on peut vouloir faire se fait très simplement : ajout de headers HTTP, lecture des headers HTTP de la réponse, passage par un proxy HTTP, etc. Seulement voilà : une fonction manque à l'appel (à mon gout), c'est la possibilité d'utiliser un proxy SOCKS :( !

Pourquoi vouloir utiliser un proxy SOCKS me direz vous ? Après tout "C'est relativement rare comme besoin et donc certainement contournable". Et bien non, là ça n'est pas contournable puisque le but du jeu c'est de faire passer notre script python par TOR, or TOR vient par défaut en tant que proxy SOCKS :)

Comment faire pour que notre script python passe par TOR du coup ? C'est enfantin : Vous télécharger socksipy, vous enregistrez le fichier que vous venez de télécharger dans le même répertoire que le script que vous voulez TORifier, et dans ce script que vous voulez TORifier vous ajoutez les 4 lignes suivantes :

import socks
import socket
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS4,"127.0.0.1",9050,True)
socket.socket = socks.socksocket

Voilà c'est fait :) Vous avez remplacé l'ouverture de socket standard de python par celle de socksipy (qui utilise le proxy TOR que vous avez configuré), donc suite à ces 4 lignes toutes les fonctions de python qui reposent sur des socket sont TORifiées, en particulier les fonctions d'urllib qui vont lire des pages web. Alors, c'était enfantin ou pas ?

  1. Et son évolution : urllib2

Le fond de la trousse à outil de papy

Par Oz le - Sécurité
File Carving Outil Reverse Engineering Réseau

J'avais initié il y a un moment une série de billets sur les outils que j'aime bien et que j'utilise en sécurité et/ou bidouillages puis j'y ai repensé cet après midi en me disant que, depuis cet éclaireur, je n'avais pas donné suite...Le temps est donc venu de parler de deux ou trois autres outils bien pratiques !

Tools - Creative Common by 'mtneer_man' on Flickr

L'outil central de ce post sera tcpflow :) ! Cette superbe commande sert à reconstituer le contenu brut des sessions TCP capturées (en live ou dans un fichier pcap). Il prend donc en argument une interface réseau (ou un fichier pcap) puis il génère, pour chaque session TCP, un fichier qui contient les données brutes qui ont transitées dans le flux TCP en question (en bref il supprime les en-têtes IP, il ordonne les paquets TCP, supprime les en-têtes TCP, et sauvegarde bout à bout le contenu complet de la session ainsi allégé). Les fichiers générés suivent une convention de nommage intuitive de type "IP1 PORT1 IP2 PORT 2" et vous pouvez donc assez facilement retrouver celui que vous voulez. A quoi ça sert me direz vous ? A tout ce que vous pouvez imaginer, mais comme je suis beau joueur (et bavard) je vous donne quelques exemples :

Un scénario d'utilisation simple consisterai à sniffer une session FTP et à vouloir récupérer les fichiers qui ont été téléchargées. Grâce à tcpflow c'est simple comme "bonjour" ! Vous lancez tcpflow et il va vous créer un fichier par session TCP sniffée. Vous allez donc avoir un fichier qui contient les commandes et réponses qui ont transitées par la session TCP de controle FTP (à destination du port 21 du serveur), et un fichier pour chaque autre session TCP. Si vous connaissez un peu le protocole ftp vous savez que les autres sessions TCP contiennent précisément chacune le contenu d'un fichier téléchargé, et que donc le fichier généré par tcpflow est l'image exacte du fichier qui a été téléchargé :) ! Job's done.

Second scénario d'utilisation simple : vous sniffez du traffic HTTP. Premier réflexe pour "gratter" des trucs intéressants : urlsnarf, voir carrément dsniff. C'est pas mal, mais si j'ai envie de récupérer les images, voir les animations flash1 comment pourrais-je faire pour extraire simplement ces fichiers de la bouillie informe d'un pcap qui contient pèle mèle les en-têtes IP et TCP et ne garantie en rien l'ordre de lecture des paquets ? Aussi compliqué que ça puisse paraitre c'est en fait presque immédiat avec tcpflow :) ! En lançant tcpflow vous obtiendrez un fichier par session TCP, si vous êtes en HTTP/1.0 vous obtenez donc un fichier dump par fichier ayant réellement transité en HTTP. Seul problème : ces fichiers contiennent les en-têtes HTTP...et si par malheurs vous êtes en HTTP/1.1 c'est encore pire : un seul fichier de session généré par tcpflow peut contenir plusieurs fichiers téléchargés en HTTP les uns à la suite des autres, avec des en-têtes HTTP intercalés dans tout ça...Donc on s'est bien débarassé des en-têtes IP, on s'est bien débarassé des en-têtes TCP, on a bien réordonné les paquets avant d'en coller le contenu bout à bout, mais il nous reste les en-têtes HTTP. C'est là qu'un petit effort de mémoire devient utile pour trouver une bidouille sale mais qui marche : foremost :) ! Pour rappel foremost extrait des fichiers à partir de suite d'octets bruts en se basant sur du pattern matching de header et de footer, foremost permet donc bien d'extraire les fichiers à partir des dump générés par tcpflow en ne faisant pas attention aux headers HTTP (testé et approuvé) ! Alors, bien sur, c'est un petit peu "sale" comme méthode, et vous raterez pas mal de fichiers (typiquement ceux qui transitent compressé puisque foremost ne sait pas les reconnaitre), mais ça a au moins l'avantage de marcher super vite pour récupérer la majeure partie de ce qui a transité :) ! De plus cette méthode est adaptable, en remplaçant foremost par un gentil petit photorec par exemple, qui a le bon gout de récupérer plus de type de fichiers que foremost (un jour il faudra vraiment que je le teste quand même...).

Dernier scénario où tcpflow peut s'avérer salutaire : si vous avez un pentest à faire sur une application client-serveur et que vous réussissez à récupérer une trace réseau. Dans ce cas là pensez à faire un petit tcpflow, ça vous permettra d'analyser tranquillement les informations qui transitent entre le client et le serveur sans avoir à vous encombrer des couches réseau basses. A la base c'est même pour ça que tcpflow a été écrit il me semble : pour faciliter la rétro-ingénierie des protocoles obscurs.

Bref vous l'aurez compris : tcpflow est un outil très pratique, et vu qu'en plus il est très léger et rapide ça serait vraiment dommage de s'en priver.

  1. pour éventuellement en extraire la bande son, la convertir en mp3, et la sauvegarder conformément à l'exception aux droits d'auteurs et droits voisins au nom de la copie privé