Blog Haypo

Aller au contenu | Aller au menu | Aller à la recherche

jeudi 8 mai 2008

Pycon FR : les Journées Python Francophones édition 2008 (JPF08)

Comme l'année passée, je participe aux Journées Python Francophones organisées par l'AFPy à Paris (à la Cité des Sciences et de l'Industrie pour être exact). Contrairement aux conférences telle que Blackhat où l'entrée coûte plusieurs milliers d'euros, Pycon FR est entièrement gratuit !

Pour les gens qui ne peuvent pas se rendre à Paris ou qui sont déjà pris ce week-end là, aucun soucis ! Les conférences seront diffusées en direct sur Internet (ils ont pensé à tout). Elles seront très certainement disponibles en téléchargement un peu plus tard.

Au niveau du programme, je vous laisse le consulter vous même. Je donne une conférence sur l'interprète PyPy et une autre sur Python 3000. Il faudrait d'ailleurs que je commence à les préparer... Pour l'anecdote, j'ai deux collègues INL qui donnent des conférences (seb et misc) :-)

Pycon FR est aussi l'occasion de rencontrer des programmeurs Python et de discuter autour d'un café ou d'une bière. Alors, viendez !

mercredi 9 avril 2008

Traitement d'image

Maintenant que j'ai écrit combien je suis indigné de la retouche photo, je vais vous présenter quelques outils de traitement d'image impressionnants :-)

Morphing de visage en 3D (1999)

Exemple de modification du visage de Tom Hanks à partir d'une seule photo (1) :

Scale2x (2001)

  • Auteur : Andrea Mazzoleni
  • Utilisation : Agrandir 2 ou 4x la résolution (en pixels) d'anciens jeux de faible résolution (typiquement 320x200 pixels en 16 ou 256 couleurs)
  • Site internet : Scale2x
  • Démonstration : Scale2x, Scale4x

Exemple de l'algorithme Scale2x :

Interactive Digital Photomontage (2004)

  • Auteurs : Aseem Agarwala, Mira Dontcheva, Maneesh Agrawala, Steven Drucker, Alex Colburn, Brian Curless, David Salesin, Michael Cohen
  • Site Internet : Interactive Digital Photomontage
  • Utilisations :
    • Créer une photo de famille où tout le monde souri à partir de plusieurs photos
    • Supprimer des personnes et objets pour créer une photo de paysage ou monument « propre »
    • Augmenter la profondeur de vue d'une photo macro (pris à quelques centimètres d'une plante ou animal)
    • Créer un panorama
    • Corriger l'éclairage d'un objet
  • Publication : Interactive Digital Photomontage (mai 2004)

Exemple de montage tronqué et simplifié (j'ai apposé moi même les marques vertes et rouges pour mieux comprendre) pour créer une photo de famille où tout le monde est heureux :

GREYCstoration (2006)

Exemple tronqué de la suppression de la cage d'un perroquet :

Seam Carving for Content-Aware Image Resizing (2007)

Exemple de réduction de la hauteur d'une photo d'un port (j'ai réduit l'ensemble avec un redimensionnement cubique pour que ça tienne dans le blog) :

Je n'ai présenté que quelques outils que je connais. Il en existe sûrement d'autres encore plus puissant ! Bientôt Blade Runner sera la réalité...

On nous cache tout, on nous dit rien !

On nous cache tout, on nous dit rien
Plus on apprend plus on ne sait rien
On nous informe vraiment sur rien

... chantait Dutronc en 1966. Et bien, il avait plutôt raison et ça ne fait qu'empirer. Pour commencer, voici deux exemples frappants :

À gauche (Curves Cereal: The Lid Said Flesh Tone) la couleur de peau change au niveau du nombril, alors qu'à droite (Parenting: All The Fun Is In The Top Half) un bébé n'a pas de bas ventre ! Ces photos sont extraites de l'excellent blog Photoshop disasters qui liste les pires photos retouchées par le logiciel Adobe Photoshop. Retoucher une photo (modifier la réalité) n'est jamais fait au hasard. Parfois, c'est pour retirer quelques détails disgracieux du visage ou du corps, dans le but de rendre beau. Rappelez vous l'histoire du magazine Paris Match qui a gommé les bourrelets du président Sarkozy (article du journal Libération, août 2007) :

Sans parler de retouche, la publicité a tendance à faire de très belles photos, parfois bien différentes de la réalité. Exemple avec le site Pundo 3000 qui compare la photo sur l'emballage (est-ce qu'il y a une mention non contractuelle écrit en tout petit ?) et le produit une fois déballé :

Je vous conseille également le page Fast Food: Ads vs. Reality. La retouche sert également à des fins politiques ! L'UMP a par exemple fabriqué de fausses preuves pour contrer les verts qui proposent de taxer les automobilistes utilisant le périphérique de Paris (L'UMP d'Ile-de-France a besoin d'une formation à Photoshop, janvier 2008) :

La retouche photo est beaucoup plus vieille que Photoshop (qui lui date de 1980). Le livre Le commissariat des archives d'Alain Jaubert (ISBN: 9782736000479) contient des photos retouchées de Lénine, Staline, Mao Zedung, Mussolini, et d'autres... À l'occasion, je scannerai peut-être quelques exemples.

lundi 10 mars 2008

Un nouvel antispam pour ce blog !

Dans le plus pur respect du syndrôme NIH, j'ai écrit mon outil de détection de spam pour les commentaires Dotclear : antispam. Je sens que rien que le nom vous fait déjà trépigner d'impatience.

Système de notation

Je me suis inspiré de mon travail sur la notation dans le projet Fusil pour noter les commentaires, ce qui n'a rien de révolutionnaire en soit (SpamAssassin le fait déjà). J'ai écrit des règles empiriques selon mes observations sur les spams. L'idée est de rechercher les caractéristiques typiques des spams puis de les transformer en règles.

Voici les règles utilisées actuellement :

  • Adresse de courriel : liste blanche/noire pour les domaines, voir conf/email_domains.txt (liste noire par défaut)
  • Mots clés : recherche de mots clés à partir d'une liste blanche/noire, voir conf/words.txt (liste noire par défaut)
  • Ratio des lettres latines majuscules et du nombre total de lettres latines : s'il y a plus de 35% de majuscules, le message gagne 5 points
  • Longueur du texte : si le texte hors liens externes contient moins de 30 lettres latines, le message gagne 2 points
  • Ratio d'url par domaine : s'il y a plus de 3 liens vers le même domaine (en moyenne), le message gagne 5 points
  • Pour chaque url, une liste blanche/noire (plutôt liste blanche) permet d'attribuer un score selon le domaine. Si l'url ne correspond à aucun domaine, elle obtient une note de +1 point

Finalement, j'utilise peu de règles pour éviter les faux-positifs (message légitime détecté comme spam). Ce n'est pas nécessaire car je n'ai pas encore vu passer de faux-positif.

Résultat sur les commentaires de ce blog

En utilisant un score initial de -3, les commentaires légitimes ont une note négative entre -3 et -2. Pour les spams, j'ai observé trois types selon la note moyenne :

  • (A) note de 0,5 à 2 : un ou deux liens, message court, texte crédible en anglais
  • (B) note de 15 à 25 : une dizaine de liens vers le même serveur avec quelques mots anglais aléatoires
  • (C) note de 150 à 200 : grosse collection de liens et liste presque exhaustive des mots clés que j'ai mis en liste noire (ex: une vingtaine de variantes de « buy cheap viagra » dans le même message)

Les spams de type (B) et (C) sont triviaux à détecter. Les plus pénibles étant les spams de type (A).

Exemple de spam pénible

Commentaire reçu aujourd'hui, j'ai remplacé les urls par xxx :

Author: brazilian <thongwaxingbrazilian@mail.com>
Website: http://xxxxxxxxx.nl/35424
IP: 218.16.224.243

- she reached for her clit. madam, i ve got arthritis,
<a href=  http://xxxxxxx.com/phpbb/barthololauries.html >waxing thong brazilian</a> and.

Le message contenait aussi deux caractères Unicode invalides (U+0092 et U+0093). Analyse avec la configuration actuelle d'antispam pour ce blog :

Match URL (+1.0): http://...
Match URL (+1.0): http://...
Match email domain (+1.0): mail.com
-stdin- score: +0.00

Le message n'est pas détecté comme spam. J'ai donc ajouté les mots clit, brazilian, thong et waxing en liste noire pour gonfler la note jusqu'à +7.

Fiabilité de l'antispam

Après une semaine de développement sur antispam, je suis plutôt content du résultat. Bien que cet outil demande beaucoup de configuration manuelle, il supprime déjà environ 90% du spam de ce blog. Sachez que je reçois à peu près 100 spams par jour sur ce blog.

L'ancien moteur de spam était fiable à 100% : il bloquait simplement tout message contenant un lien externe. J'essaye de le rendre un peu plus laxiste pour autoriser les liens externes.

Amélirations possibles

Idée pour améliorer antispam :

  • Réutiliser du code (au moins des idées) des antispams existants (ex: Spam Karma)
  • Utiliser un filtre bayésien
  • Utiliser des listes noires (URL / IP / email) dynamiques
  • Filtrage horaire et/ou selon le jour de la semaine (je pense qu'il y a peu de commentaires légitimes entre 2h et 7h)
  • Utiliser des listes blanches ou d'autres règles pour diminuer la note

Contactez moi directement si vous voulez tester antispam sur votre forum ou votre blog. L'intégration étant pénible à automatiser. Antispam est écrit en Python et distribué sous licence GNU GPL.

Comment réaliser un fuzzer ?

Après de dizaines de projets d'articles avortés (mort-nés), j'ai enfin réussi à en finir un ! C'est l'article « Comment réaliser un fuzzer ? » qui est publié dans le magazine de sécurité informatique MISC numéro 36 (mars/avril 2008). J'explique quels sont les points critiques lorsqu'on écrit un fuzzer : génération des données, surveiller la cible, auto-configuration du fuzzer, etc. Image de la première des six pages de l'article :

L'article parle indirectement de mon travail sur le projet Fusil. Un deuxième article plus pratique et dédié à Fusil devrait suivre dans le prochain MISC (reste à l'écrire...).

Je regrette d'avoir oublié la section remerciements à la fin de l'article. Alors je profite de ce blog pour remercier Sebastien Tricaud, Feth Arezki, Stéphane Marchesin et ceux que j'ai oublié pour leurs relectures attentives et leurs conseils avisés. Merci aussi à Anthony Carré pour m'avoir encouragé à écrire pour des magazines papiers :-)

Au passage, si vous êtes amateur de sécurité informatique mais que vous ne connaissez pas encore MISC, je vous en conseille la lecture. Le prix élevé de 8€ est à diviser par deux car c'est un bimensuel : ce qui donne 4€/mois. D'ailleurs, il faut deux bons mois pour digérer les articles souvent complexes ;-)

dimanche 9 mars 2008

Spam dans les forums, blogs, etc.

Le spam désigne un « message non sollicité ». Avant limité à la messagerie électronique, le spam inonde aujourd'hui Internet en utilisant n'importe quel moyen de publier du texte avec des liens externes. Les plus touchés sont les forums (ex: phpbb) et les blogs (ex: dotclear). Plus généralement, plus la cible est populaire, plus elle a de chances d'être spammée. Dès lors, n'importe quel formulaire public devient est cible potentielle.

Filtrage par test de turing

Pour limiter le spam, l'inscription aux forums est devenue pénible : besoin de confirmer l'inscription par courriel par exemple. De même, déposer un commentaire sur un blog demande souvent des talents en décodage de hiéroglyphe (captchas). Le spam doit vraiment être lucratif car qu'importe le niveau de complexité de la protection, elle est déjouée un jour ou l'autre. La meilleure parade aux captchas étant de demander à des humains de les décoder à votre place. Cette faille déjoue l'ensemble des tests de turing !

Filtrage de l'enveloppe

On pourrait alors penser à filtrer l' « enveloppe » : les informations obtenues sur l'expéditeur du message. Le nom de l'expéditeur est généré aléatoirement et pourtant crédible, on ne peut pas en faire grand chose. Son adresse de courriel est souvent crée pour l'occasion sur un serveur offrant des adresses gratuites (ex: gmail). L'adresse IP semble une bonne piste pour bloquer un spammeur. Sauf que les spammeurs ont aussi trouvé une parade : ils louent des serveurs à moindre coût pour émettre anonymement du spam. Ces serveurs peuvent faire parti d'un botnet : ordinateurs verrolés à l'insu d'internautes légitimes. Bloquer une IP empêcherait un internaute légitime de poster un commentaire. De toute manière, les spammeurs changent régulièrement de serveurs (et donc d'adresse).

Filtrage du contenu

Si l'enveloppe n'est pas une information fiable, on peut se concentrer sur le contenu du message. Bien que chaque spam soit différent, on peut tout de même reconnaître certaines caractéristiques générales :

  • un spam comporte au moins un lien externe (parfois une dizaine ou plus)
  • on retrouve les même mots tels que « porn », « download » ou encore « viagra »

Une fois de plus, ces caractéristiques ne sont pas fiables à 100%. Certains spammeurs contournent le blocage par mots-clés en modifiant légèrement le terme : « viagra » devient « v1agra » par exemple. Concernant les liens externes, on commence à trouver des liens pointant sur google.com (ex: sur groups.google.com et pages.google.com) : bloquer un domaine est donc plutôt hasardeux. Bien que les spams ne comportant aucun lien externe soient rares, bloquer tout message comportant un lien externe est très contraignant pour l'internate légitime.

Filtrage par l'obscurité

Pour déjouer les plans des robots, certains se protègent en modifiant les formulaires de leur application. Une bidouille est d'ajouter un champ au formulaire. Ce champ contient un valeur spéciale ou est laissée vide : si le bot le modifie, le message est considéré comme un spam. Ce champ peut être caché (type HTML hidden ou caché par la mise en forme CSS) ou visible, auquel cas une mention avertira l'internaute de ne pas y toucher. Malheureusement, de telles pratiques relèvent de la sécurité par l'obscurité et ne peut être utilisé à grande échelle. Une fois l'astuce connue, des robots vont la déjouer facilement.

Filtrage par pot de miel

Il existe des services mettant en place des pots de miel : forums, blogs et autres dédiés à la récolte de spam. Cette collecte permet de créer une liste noire d'URL et/ou d'IP, exemples : surbl.org et projecthoneypot.org. La technique du pot de miel ne sert qu'à limiter la diffusion d'un spam.

Aucun espoir ?

C'est en écrivant mon propre antispam pour ce blog que j'ai réalisé l'ampleur du problème. Bien qu'aucune protection citée n'est fiable à 100%, cumuler plusieurs solutions permet de bloquer l'essentiel du spam, allégeant considérablement la charge du modérateur.

Malheureusement, plus un moyen de protection est efficace, plus il est utilisé, plus les spammeurs vont se concentrer dessus pour le déjouer. La sécurité par l'obscurité semble donc conseillée voir nécessaire. Des services comme Akismet reposent justement sur ce principe. Pourtant, je m'y oppose car c'est contraire à l'esprit de partage du logiciel libre !

mardi 4 mars 2008

Scanneur de ports PortBunny

Comme je n'ai pas pu aller au 24th Chaos Communication Congress (fin décembre 2007), je me suis rabattu sur les vidéos publiées quelques temps après. J'ai beaucoup apprécié les vidéos « (2279) Deconstructing Xbox 360 security » et « (2131) Port scanning improved ». Je voudrais parler plus particulièrement de PortBunny, un nouveau scanneur de port qui a pour logo un lapin rose. Le diaporama de la présentation est disponible en ligne.

Lire la suite

Historique de la faille vmsplice()

Le chercheur en sécurité Wojciech Purczynski, employé par COSEINC et membre de l'association iSEC Security Research, a trouvé divers bugs dans l'appel système vmsplice() du noyau Linux. Cette fonction, introduite avec Linux 2.6.17, sert à envoyer des données de l'espace utilisateur vers l'espace noyau pour alimenter un pipe. Lire mon précédent billet sur l'évolution des entrées/sorties dans Linux pour les détails. Les développeurs noyau sont prévenus dès le 1er février. Cet article relate la publication, l'exploitation, puis la correction de ces failles.

Lire la suite

lundi 3 mars 2008

Évolution des appels systèmes d'entrée/sortie Linux

En juin 1998, Larry McVoy propose une nouvelle API pour les entrées/sorties dans le noyau Linux : The splice I/O model. Il propose une interface d'entrée/sortie vectorielle (scatter/gather), asynchrone et sans copie (zero copy). Le but est de maximiser les performances en évitant de recopier inutilement des zones mémoires. Les travaux pour concrétiser ses idées prendront presque une dizaine d'années.

Lire la suite

jeudi 21 février 2008

LLVM 2.2, PyPy et Ruby 1.9

J'ai écris ce petit billet pour présenter quelques évolutions dans le monde des compilateurs et des machines virtuelles.

En octobre dernier, je m'intéressais aux compilateurs C libres. Mis à part GCC, il n'y a aucun compilateur qui sort du lot. Et lundi, j'apprend que LLVM 2.2 est sorti. Pour la compilation C, LLVM repose actuellement sur gcc 4.2, mais le projet Clang vise à se débarasser de gcc ! Pour ceux qui ne connaissent pas LLVM, c'est un compilateur qui supporte de nombreux langages, mais c'est également un très bon optimiseur (20% plus rapide que gcc dans certains cas). Il ne contient pas de parseur qui traduit un fichier source en langage intermédiaire : c'est là qu'interviennent gcc/Clang pour le C. Les deux lettres « VM » de LLVM indiquent que c'est également une machine virtuelle. Le programme compilé peut embarquer un optimiseur temps réel qui va recompiler les fonctions les plus demandées pour générer un code plus rapide.

Sachant que PyPy supporte LLVM, je suis allé voir si le projet était encore vivant. Hé bien oui, un blog annonçant les derniers développements est même né fin octobre 2007 : PyPy Status Blog. J'apprend par exemple qu'ils ont écrit une nouvelle implémentation des chaînes de caractères basée sur des cordes. Le but est de limiter les recopies et allocations mémoire : un objet contient des portions des chaînes de caractères qui sont réassemblées à la demande. Concaténer deux chaînes de caractères ou extraire une partie d'une chaîne de caractère a un coût « nul ». C'est lorsqu'on va afficher la chaîne que Python va réassembler les bouts pour afficher la chaîne intégrale. C'est étonnant de voir que PyPy arrive à remettre en question les types de base en testant une nouvelle implémentation pour comparer les performances. C'est impossible de faire ça dans CPython. PyPy l'avait déjà fait pour les différentes implémentations de ramasse miettes : on peut en changer lorsqu'on compile PyPy.

Le langage Ruby n'est pas en reste : la machine virtuelle version 1.9, sortie pour Noël 2007, est trois fois plus rapide que la version 1.8 ! La nouvelle version est basée sur YARV (Yet Another Ruby VM), une nouvelle implémentation écrite en C datant de 2004. La page du projet indique l'unique but : développer la machine virtuelle pour Ruby la plus rapide du monde ! L'ancienne implémentation, MRI (Matz's Ruby Interpreter), est écrite en C et date de 1993. Je n'ai trouvé peu d'informations sur les améliorations de YARV sur MRI : pourquoi est-ce beaucoup plus rapide ? Il semble que MRI soit un interprète, alors que YARV utilise une machine virtuelle avec un bytecode (comme le fait Python depuis toujours).

mardi 19 février 2008

Profiling PHP et Javascript

Lorsqu'on cherche à accélérer une application, on a besoin d'outils pour en mesurer les performances : isoler les fonctions les plus lentes et suivre l'évolution des performances. La méthode la plus simple est de sauver une estampille de temps au début et à la fin de l'opération testée, puis de calculer la différence en répétant la mesure pour la fiabiliser. Cette méthode est loude à utiliser car il faut modifier le code source. Je vais vous présenter des outils plus simples pour PHP et Javascript.

PHP : Xdebug

L'outillage PHP est rare et de piètre qualité. Néanmoins, je suis tombé sur XDebug qui, pour une fois, semble d'excellente facture. Ce projet est un extension PHP au moteur Zend qui permet de mesurer les performances d'un script PHP, d'analyser la couverture de code, ou encore de déboguer interactivement un script.

Pour compiler le projet sous Linux, vous aurez besoin de l'outil phpize qui va générer le script configure. Cet outil fait parti du paquet Ubuntu php5-dev. Bizzarement, Ubuntu (/usr/lib/command-not-found) ne propose pas d'installer le paquet php5-dev quand on tente d'exécuter phpize. Incapable de corriger le problème, j'ai ouvert un rapport de bug.

Une fois le module installé (./configure && make && sudo make install), il faut l'activer en ajoutant une option zend_extension à PHP. Sous Ubuntu, il suffit de créer un fichier /etc/php5/conf.d/xdebug.ini avec le contenu suivant (adaptez le chemin si besoin est) :

# configuration for php Xdebug module
zend_extension="/usr/lib/php5/20060613+lfs/xdebug.so"
xdebug.profiler_enable=1

Maintenant, pour chaque hit sur une page PHP, un fichier /tmp/cachegrind.out.pid sera généré. Les résultats peuvent manipulés avec l'excellent KCacheGrind. Un des graphiques les plus utiles est l'arbre ci-dessous :

Note : Pour l'installation, je me suis aidé du guide Installer Xdebug pour PHP 5.2.

Javascript : Venkman et Firebug

Pour profiler Javascript, là encore, il y a peu d'outils. J'ai testé le débogueur Javascript Venkman dans Firefox. Malheureusement, j'ai rapidement été confronté à un bug Firefox : Venkman crashs on profiling after clearing profile data. J'ai perdu beaucoup de temps à isoler ce bug avec gdb et Valgrind. Et dire qu'un rapport de profiling Venkman est une longue page HTML incompréhensible...

J'ai perdu tellement de temps sur Venkman que je ne me suis pas aperçu que j'avais déjà la solution sous les yeux ! L'excellente extension Firebug contient déjà des outils de profiling Javascript. Pour profiler une page, activez Firebug, cliquez sur le bouton « Profile » (c'était vraiment sous mon nez), chargez la page à tester, puis recliquez sur « Profile ». Vous obtiendez un joli tableau synthétique où on peut changer la méthode de tri dynamiquement. Voir le tableau (tronqué) ci-dessous :

Note : Je n'ai pas eu le temps de tester Drosera qui est le profiler Javascript de WebKit.

Mots de la fin

Pour finir, petit rappel : une optimisation n'est profitable que lorsqu'on gagne plus de 5% (voir 20%). Parfois, un changement sera une légère accélération sur une machine, et un léger ralentissement sur une autre. Les micro-optimisations sont à bannir. Souvent, un algorithme qui convenait à de petites quantités de données se révèle avoir une complexité en O(n^2) voir O(n^3) et effondre les performances. Il faut alors changer d'algorithme. Autre méthode : limiter les appels aux fonctions lentes, en utilisant un cache par exemple.

Le fournisseur d'accès à Internet Free

Depuis Octobre 2006, je suis abonné au fournisseur d'accès Internet Free. Situé à 900 mètres du DSLAM, l'affaiblissement de ma ligne (ADSL 2+) est de 13 dB. Le téléphone (VoIP) fonctionne plutôt bien et la télévision également : je peux enregistrer une émission tout en regardant un film. L'appel à l'international est gratuit dans de nombreux pays et bon marché pour les autres. Note : l'appel aux États-Unis est gratuit... mais pas pour l'Alaska (qui un état des États-Unis) !? L'appel en Alaska coûte 22 centimes la minute (tiens, je vois dans la grille tarifaire que l'appel en Alaska est aussi noté comme gratuit !?).

Employé en télétravail, la stabilité de ma connexion Internet est primordiale. De mémoire, en 17 mois, j'ai du avoir à peu près 30 minutes d'interruptions de services (plus d'internet du tout). Ce qui donne une fiabilité de 99,996%. Début 2007, la télévision était parfois hors-service, mais ça n'arrive plus aujourd'hui. J'ai choisi le mode PATATE de l'option Fastpath : « synchronisation ADSL sans bridage (jusqu'à 24 Mbit/sec) et sans seuil minimum sur le bruit, mais peut entraîner des erreurs et des pertes de paquets ».

Fin novembre dernier, le code source du site grenouille.com est passé sous licence AGPLv3. J'en ai profité pour m'inscrire à ce service : consultez mes graphiques de vitesse de téléchargement. La vitesse de téléchargement varie entre 800 et 1200 Ko/sec, la vitesse d'envoi semble bridée à 100,0 Ko/sec et le ping est d'environ 35 ms.

C'est vraiment très agréable d'avoir une aussi grosse bande passante avec une si bonne fiabilité. Pour finir, je paie 29,99€ en tout pour Internet, la télévision et le téléphone.

Note : Le support Free est difficilement joignable et totalement incompétent. Si vous avez le moindre problème avec votre connexion, c'est la croix et la bannière... Free est plutôt binaire : soit ça marche (bien), soit ça marche pas (du tout).

lundi 4 février 2008

Sécurité des réseaux sociaux

Les années 2003 et 2004 ont vu fleurir un grand nombre de réseaux sociaux : LinkedIn, MySpace, del.icio.us, Orkut, Facebook, Flickr, ... La popularité de ces sites Internet a rapidement explosé : le nombre de membres se compte en millions. MySpace comptait 100 millions de membres en juillet 2007. Malheureusement, la sécurité de ces réseaux est régulièrement ébranlée. Pour le passage à l'année 2004, Annalee Newitz publiait l'article Defenses lacking at social network sites sur SecurityFocus. Extrait : « Williams explained that "XSS is amazingly widespread. Plus, XSS vulnerabilities are easy to discover and exploit" ». Les problèmes sont donc connus depuis longtemps. Voyons ce qu'il en est aujourd'hui.

Collecte d'informations : attaque ciblé et revente d'informations

Il y a un mois, Mary Landesman écrivait que les utilisateurs de réseaux sociaux donnent des détails sur leur vie, amour, travail, et loisirs qu'ils n'oseraient jamais dévoiler à un étranger dans un bar. Ces informations sont extrêmement utiles pour une attaque ciblée. L'attaque typique en ingénierie sociale est l'hameçonnage : envoi d'un courriel demandant à la victime d'aller sur un site Internet imittant l'habillage du site connu, ebay ou paypal par exemple, où elle sera invitée à saisir son identifiant, mot de passe ou autres informations confidentielles.

Certains réseaux sociaux indiquent ouvertement qu'ils revendent vos informations à des sociétés. Facebook en est un exemple : la section « Vie privée : la récolte et la vente des informations personnelles à des entreprises privées » de l'article Facebook de Wikipédia est forte instructive.

Heise-security vous conseille de ne pas noter d'information critique réelle telle que votre date de naissance ou votre adresse : posez-vous la question « est-ce que je dirai ça à un passant dans la rue ou à mon patron ? » avant de poster n'importe quel contenu. Petite anecdote amusante : How Facebook Ended My Marriage. Un couple ayant décidé de retirer leur fiançaille de leur profil Facebook, parce que c'était trop personnel, a provoqué une petite tornade à travers le monde. Plusieurs amis ont compris que leur mariage était annulé, certains allant même jusqu'à transmettre l'information par blog interposé.

Infection des sites Internet des réseaux

Comme on pouvait s'y attendre, les sites Internet des différents réseaux sociaux sont régulièrement infectés dans le but de prendre le contrôle du profil des membres ou bien d'infecter l'ordinateur des membres.

Samy is my hero

Le premier ver qui a fait parler de lui est le ver Samy is my hero injecté dans MySpace en octobre 2005. Le ver inscrit la victime comme ami de Samy et ajoute le message « but most of all, samy is my hero » au profil de la victime. L'auteur, Samy, a d'ailleurs monté une page web dédiée au ver. MySpace se protégait en bloquant le mot « javascript », mais Samy a outrepassé cette protection en écrivant le mot javascript avec un retour à la ligne entre java et script. Le code HTML est de la forme :

<div id=mycode style="background: url('java
script:eval(document.all.mycode.expr)')" expr="EXPLOIT"></div>

Le ver n'exploite pas vraiment de vulnérabilité de MySpace, mais plutôt du navigateur web. Pour que le ver fonctionne, ce dernier doit interprèter le Javascript inscrit dans le style CSS. Or un style CSS n'est pas prévu pour ça et le navigateur ne devrait pas le faire. Le ver fonctionnait sous Internet Explorer (Windows), mais ne touchait pas les versions récentes de Safari (Mac OS X) par exemple.

Le ver infectant automatiquement les amis des victimes (effet boule de neige), Samy a réussi à récolter un million d'amis MySpace en seulement 18 heures.

Failles Flash et WMF

En juillet 2006, MySpace a subi deux nouvelles infections. La première utilise une vulnérabilité du greffon Flash qu'Adobe avait corrigé il y à peine une semaine, lire MySpace Attacked by Flash Worm et Myspace Hack spreading like wildfire: SPAIRLKAIFS (16 juillet 2006). Le ver injecte du code HTML de la forme suivante dans le profil MySpace de la victime et installe un spyware sur l'ordinateur de la victime :

<embed allowscriptaccess="never" src="http://i105.photobucket.com/albums/mff225/yrkblack/redirecft.swf">

Quatre jours plus tard (20 juillet 2006), une publicité pour le site « DeckOutYourDeck.com » utilise une vulnérabilité WMF de Windows. Un cheval de troie est alors utilisé pour pour installer ClickSpring, un logiciel qui affiche de la publicité. Selon le Washington Post, ClickSpring a été installé avec succès sur un peu plus d'un million d'ordinateurs.

Livre d'or Orkut

En décembre 2007, c'est le réseau Orkut qui est infecté par un ver Javascript. Selon Symantec, le ver a modifié le profil d'environ 700.000 membres en 24 heures. Il modifiait le livre d'or (guest book) pour y injecter un lien vers du code Javascript. Des courriels ont également été envoyés aux victimes pour les persuader de visiter des livres d'or infectés. Les victimes étaient aussi inscrites automatiquement dans la communauté « Infectados pelo Vírus do Orkut » (infecté par le virus Orkut, en portugais). Le javascript génère du code Flash à la volé pour exécuter du code malicieux sans que la victime ne s'en rende compte. Le ver était resteint à Orkut, l'ordinateur de la victime n'était pas infecté.

Widget Facebook

Facebook propose à ses membres d'ajouter des widgets Javascript à leur compte. Début janvier dernier, un widget verollé installait le spyware Zango sur l'ordinateur des visiteurs. Le widget utilisait une <iframe> qui pointait sur l'installeur de Zango.

Infection par bandeaux publicitaires

Quelques jours après Facebook, un serveur de bandeaux publicitaires distribue du code verrolé exploitant des vulnérabilités des navigateurs web pour infecter l'ordinateur de la victime. De nombreux sites sont touchés, en particulier : MySpace, Excite.com et Blick.ch. Les bandeaux publicitaires installent des chevaux de troie comme RBot, SDBot et Spybot.

Vulnérabilités des barres d'outil

Pour faciliter la navigation, certains réseaux sociaux proposent des extensions pour votre navigateur web. Malheureusement, chacun s'est vu attribuer une faille. Petite liste d'exploits milw0rm :

Second Life

L'univers Second Life n'est pas en reste. De plus en plus populaire, il intéresse également les pirates.

Le premier événement majeur date de novembre 2006 : un ver appelé Grey Goo installe des anneaux d'or dans l'univers. Le ver a beaucoup ralentit Second Life qui a du être mis hors service pour se débarasser du ver.

En septembre 2007, une faille a été trouvée dans le client Second Life. Elle utilisait le scheme « secondlife:// » dans une <iframe> pour voler l'identifiant et le mot de passe de la victime en réalisant une fausse authentification.

Plus drôle, des chercheurs ont démontré que la vulnérabilité Quicktime pouvait être exploité dans Second Life. Ils ont fabriqué une vidéo qui volait 12 Linden dollars (5 cents américains) et faisait dire à sa victime « I got hacked » !

Comment se protéger

Les attaques présentées dans cet article utilisent souvent de multiple vulnérabilités pour monter une attaque complexe : navigateur web, Javascript, Flash, QuickTime, etc. D'une manière générale, il faut s'assurer que tous les logiciels de votre ordinateur sont à jour. Avec une distribution Linux, c'est trivial, des outils sont déjà prévu pour ça. Sous Windows, vous pouvez par exemple utiliser le logiciel Personal Software Inspector de Secunia. N'utilisant pas Windows, je ne l'ai pas testé.

Pour la navigation sur Internet, je vous conseille d'utiliser Firefox plutôt qu'Internet Explorer. Firefox est le seul navigateur web a avoir une protection Javascript efficace : l'extension NoScript.

Conclusion

Comme nous avons pu le voir, les réseaux sociaux deviennent une cible de choix car ils offrent aux pirates un moyen d'infecter un million de membres et/ou d'ordinateurs en une seule journée. Les premières attaques étaient l'œuvre d'hackers voulant démontrer leurs capacités d'outrepasser les protections. Aujourd'hui, c'est un marché lucratif qui sert à installer de la publicité et chevaux de troie sur l'ordinateur des victimes.

De nombreuses sociétés travaillent main dans la main pour rendre le web plus sûr : consultez le site OWASP pour en savoir plus.

Une fois n'est pas coutume, je voudrais dédicasser ce billet à Florent ;-)

samedi 26 janvier 2008

Failles de sécurité liées à Unicode

La complexité du jeu de caractères Unicode est source de nombreuses failles de sécurité. Cet article présente quelques failles récentes pour illustrer les problèmes qu'on peut rencontrer.

Écriture bidirectionnelle (RLO et LRO)

Le premier type que je veux présenter n'est pas un bug d'Unicode, mais une fonctionalité ! On peut changer l'ordre dans lequel est écrit le texte. Un dieu du CSS, Stu Nicholls, l'utilise pour afficher son adresse email en clair, alors qu'en fait elle est écrite à l'envers dans la souce HTML ! Le style CSS est « unicode-bidi:bidi-override; direction: rtl; ».

Sauf que des malins ont pensé à utiliser cette fonctionnalité pour tromper l'œil humain en cachant l'extension d'un nom de fichier. L'article Deceptive file names under Vista (septembre 2007) montre comment une programme Windows (.scr) est affiché comme une image JPEG (.jpg) dans Windows Vista. Windows XP ne supporte pas cette fonctionnalité et affiche donc les codes de contrôle Right-to-left override (RLO, U+202E) et Left-to-right override (LRO, U+202D), montrant alors la supercherie.

Halfwidth and Fullwidth Forms

Les failles de type « directory traversal » outrepassent les mesures de sécurité et permettent de lire un fichier arbitraire. En PHP, on trouve souvent des failles du type « index.php?page=../../../../etc/passwd ». Les webmestres se protègent en interdisant la chaîne « ../ » dans le nom du fichier utilisé. Quelques fois, il est possible d'outrepasser cette protection en spécifiant le chemin complet du fichier. Une variante est de jouer entre les caractères « / » et « \ » selon le système d'exploitation. Certains serveurs et/ou systèmes d'exploitations acceptent également « .../ » dans le nom du fichier.

Ce type de bug est aujourd'hui connu et corrigé dans la majorité des serveurs. Dumoins, c'est ce qu'on pensait jusqu'à cette annonce : Unicode encoding can be used to bypass intrusion detection systems (juin 2007). L'idée est d'utiliser les caractères halfwidth et fullwidth de la plage Unicode U+FF01-U+FFEE. Le soucis est que les URL sont normalisées après avoir été validées !

Exemple de normalisation (décomposition canonique) avec Python 2.5 :

>>> from unicodedata import normalize
>>> char=normalize('NFKC', u'\uFF0E'); print "%r (%s)" % (char, ord(char))
u'.' (46)
>>> char=normalize('NFKC', u'\uFF0F'); print "%r (%s)" % (char, ord(char))
u'/' (47)
>>> char=normalize('NFKC', u'\uFF3C'); print "%r (%s)" % (char, ord(char))
u'\\' (92)

Séquence UTF-8 invalide

Il faut savoir que 7 ans plus tôt, un bug similaire avait déjà été découvert dans Microsoft IIS (octobre 2000). Cette fois-ci, le problème était la normalisation de l'encodage UTF-8. IIS était trop laxiste : il acceptait les séquences invalides, c'est-à-dire lorsqu'un code a une séquence plus longue en octets que la taille normale. Exemple : le caractère point « . » (U+2E) s'encode « 0x2E » en UTF-8, mais peut également être encodé (0xC0, 0xAE) (forme invalide).

Note : Le langage Java utilise d'ailleurs une forme non standard d'UTF-8 : le caractère nul est encodé volontairement (0xC0, 0x80) pour éviter qu'une chaîne soit tronqué par une fonction C bas niveau (telle que strcpy).

Confusion entre octet et caractère

Depuis que le jeu de caractères ASCII a été inventé, il existe une confusion entre la notion d'octet et de caractère. C'est encore plus vrai avec les jeux de caractères ISO-8859. La très grande majorité des programmes mélangent allègrement octets et caractères sans se poser de question. D'une manière générale, ce n'est pas trop gênant. On retrouve cette problématique lorsqu'on manipule du HTML : si on tronque du texte HTML à une position donnée, il est possible qu'on coupe en plein milieu d'une balise ou d'un caractère écrit sous la forme « &nom; ». Exemple : « J'ai mang&eacute; ! » tronqué au 12e caractère donne « J'ai mang&ea ».

Exemple de vulnérabilité : WordPress Charset SQL Injection Vulnerability (décembre 2007). Le problème apparait lorsque la base de donnée utilise un jeu de caractère chinois : Big5 ou GBK. La fonction qui échappe les chaînes de caractères SQL utilise addslashes() qui travaille sur des octets et non pas des caractères. La séquence d'octets (0xB3, 0x27) est alors échappée en (0xB3, 0x5C, 0x27). Or 0xB35C est un caractère valide en Big5, et on obtient donc une apostrophe seule !

Exemple avec Python 2.5 :

>>> user='\xB3\x27'
>>> sql=user.replace("'", "\\'")
>>> print unicode(sql, "big5")
許'

Le problème de fond est que PHP ne supporte pas Unicode. Il va falloir attendre PHP6 qui est en cours de gestation. Notez que ce genre de bug touche également les programmes écrit en C, Java ou même en Python. Bien que Python propose le type unicode, il est rarement utilisé bien que complet. Le module re (expression régulières) supporte les expressions unicode. Python 3000 vise, entre autre, à encourager l'adoption d'Unicode comme type par défaut des chaînes de caractères.

Autres bugs des implémentations d'Unicode

La bibliothèque Qt de Trolltech calculait mal la longueur des chaînes UTF-8 (il manquait un "+1") : Bugzilla Bug 269001: CVE-2007-4137 QT off by one buffer overflow (rapport de bug avec patchs pour Qt3 et Qt4, août 2007).

La fonction repr() du langage Python n'allouait pas assez de mémoire pour les chaînes Unicode : buffer overrun in repr() for unicode strings (août 2006, lire aussi le CVE-2006-4980). La fonction repr() n'allouait que 6 octets par caractère en ne considérant que la forme « \uXXXX », or la forme « \Uxxxxxxxx » peut être nécessaire et consomme 10 octets par caractère.

Conclusion

Unicode regorge de fonctionnalités qui sont souvent méconnues. Mal utilisées ou utilisées à mauvais escient, ça peut faire très mal. Je pense qu'il manque des fonctionalités de sécurité dans les bibliothèques Unicode. Les encodages non standards doivent être rejettés ou une alerte doit être déclanchée. Le module mod_security d'Apache propose ce genre de fonctionnalité : voir SecFilterCheckUnicodeEncoding et @validateUtf8Encoding. Il faudrait pouvoir désactiver toutes les fonctionalités Unicode et n'activer que ce dont on n'a besoin pour éviter les effets de bord indésirables.

Jeu de caractères Unicode

Unicode est un hydre : lorsqu'on découvre Unicode, chaque point éclairci va faire surgir deux nouvelles questions ! Cet article tente de démystifier Unicode en présentant quelques particularités de ce jeu de caractères.

Unicode 5.0

Unicode est un jeu de caractères incluant tous les autres jeux de caractères existant : c'est un surensemble qui est donc forcément plus gros. La dernière version publiée date de juillet 2006 : la norme Unicode 5.0.

Nombre de caractères :

  • Caractères graphiques : 98.884 (lettres, marqueurs, chiffres, ponctuations, symboles et espaces)
  • Code de formatage : 140 (séparateurs de ligne et de paragraphe, sens du texte, ...)
  • Code de contrôle : 65 (héritage de l'ASCII)
    • U+00–U+1F
    • U+7F–U+9F
  • Caractères à usage privé : 137.468 (l'émetteur et le récepteur peuvent définir leurs propres codes)
    • U+E000–U+F8FF
    • U+F0000–U+FFFFD
    • U+100000–U+10FFFD
  • Codes surrogates : 2.048
    • U+D800–U+DBFF : Low surrogates
    • U+DC00–U+DFFF : High surrogates
    • Pour UTF-16, les codes U+10000 à U+10FFFF sont encodés sur deux mots de 16 bits :
      • On retire 0x10000 au code : 0x10000..0x10FFFF => 0x0000..0xFFFF
      • On découpe le résultat en deux valeurs de 10 bits chacune
      • Finalement, le premier mot est : 0xD800 + (code-0x10000) & 0x003FF (10 bits de poids faible)
      • Et le deuxième mot est : 0xDC00 + ((code-0x10000) >> 10) & 0x003FF (10 bits de poids fort)
    • Les surrogates sont donc des codes Unicode interdits pour éviter de confondre un code avec un mot d'UTF-16
  • Non caractères : 66
    • Codes terminés par 0xFFFE en hexadécial : U+FFFE, U+1FFFE, ... U+10FFFE (17 codes). Codes interdits pour que le code U+FEFF puisse servir comme marqueur d'endian pour les encodages UTF-16 et UTF-32.
    • Codes terminés par 0xFFFF en hexadécial : U+FFFF, U+1FFFF, ... U+10FFFF (17 codes). Peuvent être utilisé dans une implémentation d'Unicode comme « valeur maximale ».
    • U+FDD0–U+FDEF
  • Codes réservés : 875.441 (réservés pour des usages futurs)

Unicode 5.0 contient donc 1.114.112 codes caractères : codes 0x000000 à 0x10FFFF.

Les codes 0x0000 à 0xFFFF constituent ce qu'on appelle le « Plan multilingue de base » (abrégé BMP en anglais).

Sérialisation d'Unicode

Un octet ne pouvant contenir que 256 codes différents, Unicode a besoin d'un encodage sur plusieurs octets pour chaque code. Il existe de nombreux encodages :

  • UTF-7 : mots de 7 bits (le 8e bit peut être utilisé comme bit de parité)
  • UTF-8 : mots de 8 bits
  • UTF-EBCDIC : mots de 8 bits (compatible avec le jeu de caractère EBCDIC)
  • CESU-8 : mots de 8 bits (mélange entre UTF-8 et UTF-16)
  • UTF-16 : mots de 16 bits (UTF-16LE et UTF-16BE pour little endian et big endian)
  • UTF-32 : mots de 32 bits (UTF-32LE et UTF-32E)

Il existe également les algorithmes SCSU et BOCU qui servent à compresser un texte Unicode sérialisé.

Exemple avec Python 2.5 :

>>> u'é'.encode('utf8')
'\xc3\xa9'
>>> u'é'.encode('UTF-16LE')
'\xe9\x00'
>>> u'é'.encode('UTF-16BE')
'\x00\xe9'

Caractère U+AF05 :

>>> u'\uAF05'.encode('utf8')
'\xea\xbc\x85'
>>> u'\uAF05'.encode('UTF-16LE')
'\x05\xaf'
>>> u'\uAF05'.encode('UTF-16BE')
'\xaf\x05'

Encodage Punycode

L'algorithme Punycode, normalisé par la RFC 3492, sert à convertir un nom de domaine Unicode sous forme ASCII : lettres A à Z, chiffres 0 à 9 et le caractère « - ». L'algorithme est réversible : on peut convertir un punnycode en Unicode sans perte d'information. Cet encodage est surtout utilisé pour les noms de domaine Unicode (serveurs DNS) : les Internationalized Domain Names (IDN). Lire le billet de Stéphane Bortzmeyer sur les IDNA.

Exemple avec Python 2.5 :

>>> from encodings.idna import ToASCII, ToUnicode
>>> ToASCII(u'café')
'xn--caf-dma'
>>> print ToUnicode('xn--caf-dma')
café

Normalisation d'un caractère

On peut composer un caractère. Le caractère « ä » peut s'écrire « a » + umlaut (U+308). Il existe trois caractères correspondant dans la table Unicode :

  • U+61 : « a », lettre A
  • U+E4 : « ä », lettre A avec umlaut
  • U+308 : « ¨ », umlaut

Donc U+E4 et (U+61, U+308) sont équivalents. Il existe des outils pour normaliser selon les différentes formes :

  • NFD (Forme normale D) : décomposition canonique
  • NFC (Forme normale C) : décomposition canonique suivie d'une recomposition des caractères précomposés
  • NFKC (Forme normale KC) : décomposition de compatibilité, c'est-à-dire remplace les caractères de compatibilité par leurs équivalents
  • NFKD (Forme normale KD) : décomposition de compatibilité suivie d'une décomposition canonique

Exemple avec Python 2.5 (Décompose puis Compose) :

>>> from unicodedata import normalize
>>> list(normalize('NFD', u'ä'))
[u'a', u'\u0308']
>>> list(normalize('NFC', u'a\u0308'))
[u'\xe4']

Conclusion

Unicode est un sacré bordel ! Les gens habitués à manipuler ASCII et son jeu de caractère ridicule de 128 codes sont perdus. Même ceux habitués à ISO-8859-15 flambant neuf avec son euro bling-bling (€) sont perdus car ils connaissent presque les 256 codes par cœur. Unicode contient plus d'un million de codes qu'on peut écrire d'un millier de manières différentes !

Néanmoins, c'est un pari sur l'avenir car on peut enfin mélanger sans broncher des textes dans n'importe quel langue. D'ailleurs, on peut changer l'ordre d'affichage pour les écritures de droite à gauche et inversement. Les encodages UTF-8, UTF-16 et UTF-32 simplifient la détection de l'encodage et sont plus simples que leurs ancêtres (ex: Shift JIS et ses nombreux codes de contrôle). UTF-8 est le charset ultime pour l'interopérabilité car il n'a pas de problème d'endian, est simple à détecter et peu coûteux en place pour l'encodage d'ISO-8859-1.