Skip navigation.

devloop :: blog

Blog sur la sécurité informatique, la programmation, Linux et le Web

Posts tagged with "coding"

Démo de Wapiti

, , ,

Wapiti SVN - scan with terminal colors

L'occasion pour tester à la fois recordMyDesktop et la plateforme d'hébergement de vidéos Vimeo.
Le résultat est largement satisfaisant. Les vidéos ogg sont légères tout en restant de bonne qualité et le réencodage sur Vimeo ne détériore pas trop la vidéo :smile:

Dans cette vidéo vous pouvez voir Wapiti (dans la version actuelle sur le SVN) lancé sur mes scripts de test perso (ne faites donc pas attention au noms de variables...)
Vous pouvez constater que les messages sont en bonne partie français (internationalisation en fr, es, en) :smile: Je pense en avoir terminé avec l'affichage en mode console (couleurs, niveau de bavardage).
En revanche je vais devoir travailler sur la génération des rapports qui pose problème (on ne peut pas insérer de la même façon certains caractères dans un rapport au format txt et un rapport au format html).

Encore et toujours des modifications à apporter p:

Wapiti 1, MySQL 0

, , , ...

Le développement de Wapiti continue doucement mais sûrement. J'ai mis en place le système de module dont j'avais parlé, ça commence à avoir de la gueule :smile:
Dans les dernières révisions sur le SVN j'ai pu réimplémenter l'injection SQL en aveugle et la recherche des XSS permanents qui avaient été virés dans les changements.

Aujourd'hui j'ai joué un peu avec Mutillidae (après quelques minutes à modifier le code car pas assez "strict" pour ma config).
Ca a permis de trouver quelques problèmes stupides avec l'injection en aveugle, notemment l'utilisation du mot clé "AND" qui est bien moins efficace qu'un bon "OR" p: et aussi quelques payloads simples que j'ai rajouté.

Sans ces 2/3 payloads simples, Wapiti injectait la fonction SQL "benchmark(10000000,MD5(1))" alors qu'il aurait pu tout aussi bien le faire avec un "sleep()" (si un caractère supplémentaire n'avait pas été présent).
La différence entre ces deux fonctions c'est que la première prend beaucoup de ressources. On voit les requêtes s'entasser sous MySQL ("show processlist;") et le process passe à plus de 95% d'utilisation du CPU... et finalement MySQL semble baisser les bras : le processus tourne encore mais le serveur ne traite plus les requêtes.

Wapiti vainqueur par K.O. p:

Maintenant je compte vérifier la façon dont est géré la verbosité dans les différents modules puis je vous reparlerais prochainement du système de modules et comment en créer de nouveaux ;-)

Pour obtenir la dernière version du SVN :
svn co https://wapiti.svn.sourceforge.net/svnroot/wapiti wapiti

Installez Python sans droits d'administrateur

, ,

Un outil bien pratique que j'ai cherché à une époque sans jamais trouver et sur lequel je suis finalement tombé : Portable Python

Comme son nom l'indique ça permet de disposer d'un environnement "portable" de Python et ça peut s'installer sans disposer de droits d'administrateur (pratique pour se la péter au taff) :cool:

Python : Chargement dynamique de modules - un système d'extensions

, , ,

Je cherchais une méthode pour mettre en place un vrai système "modulaire" de modules en Python, comme un système de plugins où les extensions seraient chargées dynamiquement sans que les informations concernant ces modules soient "hardcodées" dans le programme.
On pourrait ainsi rajouter directement les modules dans un répertoire sans avoir à les déclarer à un autre endroit dans le code. Bien sûr ça suppose que chaque module soit créé sur un même modèle car il faut tout de même savoir à quoi on souhaite accèder p:

Finalement j'ai trouvé l'astuce suivante qui peut vous intéresser ;-)
Soit l'arborescence suivante :
.
|-- launcher.py
`-- modules
    |-- __init__.py
    |-- abcd.py
    |-- plop.py
    `-- truc.py

Le répertoire modules est le dossier qui contient les extensions. Le fichier __init__.py contient uniquement une ligne qui définit les modules présents dans le dossier (pour se simplifier la tâche) :
__all__ = ["plop", "abcd", "truc"]

Les fichiers abcd.py, plop.py et truc.py contiennent chacun une classe dont le nom correspond au fichier avec un constructeur et une méthode run().
La classe plop a la particularité de contenir une fonction special(). Pour l'exemple, le contenu du fichier plop.py est le suivant :
class plop:
  def __init__(self):
    print "Constructeur de plop"

  def run(self):
    print "run() de plop"

  def special(self):
    print "Fonction special() de plop"

Enfin, le contenu du fichier launcher.py qui a pour rôle de charger dynamiquement ces modules en aveugle est le suivant :
#!/usr/bin/env python
import modules
for mod_name in modules.__all__:
  mod = __import__ ("modules." + mod_name, fromlist=modules.__all__) # on charge le module
  mod_instance = getattr(mod, mod_name)() # on appelle le constructeur
  mod_instance.run()
  if hasattr(mod_instance, "special"):
    mod_instance.special()

Son lancement provoque la sortie suivante :
Constructeur de plop
run() de plop
Fonction special() de plop
Constructeur de abcd
run() de abcd
Constructeur de truc
run() de truc

On pourrait s'affranchir encore plus du code en lisant le contenu du répertoire modules pour obtenir le nom des fichiers (par glob par exemple).
On pourrait aussi mettre dans chaque classe un attribut définissant sa priorité de lancement pour effectuer un système de chargement dans le même style que init.d :smile:

Stéganographie et Unicode (UTF-8)

, , , ...

Mise en bouche

Jetez un oeil à ce texte, extrait d'une page Wikipedia :

The frequency of letters in text has often been studied for use in cryptography, and frequency analysis in particular. No exact letter frequency distribution underlies a given language, since all writers write slightly differently. Linotype machines sorted the letters' frequencies as etaoin shrdlu cmfwyp vbgkqj xz based on the experience and custom of manual compositors.

Et maintenant jetez un autre oeil au texte suivant :

Thе frequеncy of lettеrѕ in tеxt Һas oftеn beеn studіed for uѕe in сryptogrарhу, and freqυеncy analуѕis in pаrticular. Νо eхасt lettеr frequеncy dіstribution underlies a given language, since all writers write slightly differently. Linotype machines sorted the letters' frequencies as etaoin shrdlu cmfwyp vbgkqj xz based on the experience and custom of manual compositors.

Vous semblent-ils différents ? Peut-être avez vous remarqué une particularité dans l'un des texte... car l'un d'entre eux contient un message secret :sherlock:
Jeter un coup d'oeil au code HTML de cette page vous donnera certainement un indice, pourtant j'aurais très bien pu vous montrer deux textes bruts (plain text) et vous n'aurez pas forcément remarqué plus de particularités.

L'unicode : qu'est-ce que c'est et pourquoi on nous emmerde avec

L'unicode est une norme de codage des caractères destinée à être utilisée massivement pour rassembler et remplacer les normes existantes de différents pays.
On pourrait représenter l'unicode comme une énorme table de corresponde entre les caractères et leurs valeurs informatique comme on peut en trouver pour l'ASCII.
Pendant longtemps, chacun y allait de sa norme de codage des caractères : ASCII et ISO 8859-1 pour les occidentaux, le Big5 pour les chinois, le KOI8-U pour les russes, le Shift-JIS ou encore le ISO 2022 pour les japonais.
On peut imaginer que cette diversité de normes n'arrange pas les développeurs qui souhaitent rendre leurs logiciels accessibles au plus de personnes possibles, quelque soit leur langue.

Unicode se "décline" en plusieurs formats : UTF-8, UTF-16 et UTF-32.
Il y a aussi l'UTF-7 utilisé par des protocoles d'envoi de courrier et on parle de UTF-5 ou d'UTF-6, chacun ayant pour spécificité d'être compatible avec "alphabet" prédéfini comme ceux (limités) utilisés pour composer une adresse email ou un nom de domaine.
Le nombre situé derrière les caractères UTF correspond au nombre de bits minimum nécessaire pour l'encodage d'un caractère.

Le format dont cet article parlera sera l'UTF-8 qui est principalement utilisé par nous autre européens ou américains.
Ce format là a en effet le grand avantage d'être rétro-compatible avec l'ASCII, c'est à dire que la plupart des caractères que l'on utilise sont encodés sur un octet, exactement comme ils l'étaient auparavant :up:
Ce "miracle" tient sur le fait que l'UTF-8 utilise les premiers bits de chaque octet pour déterminer s'il a affaire à nos bons vieux caractères où s'il doit chercher dans des tables plus exotiques.
Ainsi notre petit "a" sera codé 0x61 en hexa comme c'était le cas en ASCII mais le "à" avec accent tiendra sur deux caractères et se codera 0xC3A0.
La page Wikipedia sur l'UTF-8 montre quels bits sont utilisés sur chaque octet.

L'UTF-8 est donc, comme d'autres formats d'unicode, extensible. Comme dit sur cette page, on pourrait qualifier le format UTF-8 de raciste : quand nos caractères sont encodés sur un ou deux octets, les thaïlandais ou les koréens ont droit à 3 octets par caractère ! nervous
Pas de quoi les motiver à utiliser UTF-8, heureusement l'UTF-16 et l'UTF-32 mettent tout le monde à un niveau d'égalité (toutefois l'UTF-32 prend comme son nom l'indique 4 octets par caractère :frown: )

UTF-8 : représentation, encodage et décodage en Python...

Quand on veut nommer un caractère en unicode, on utilise généralement la forme "U+XXXX""XXXX" est un nombre hexadécimal dont la taille peut varier.
Pour "fouiller" dans l'unicode, il y a trois sites quasi-indispensables :
decodeunicode.org : une mine d'or à l'interface soignée.
FileFormat.Info : très pratique, le sites offrent aussi des ressources en dehors d'unicode
Unicode.org : le site officiel avec les tables de caratères au format PDF.
Unimap (unipad.org) : assez simple mais efficace.

Si vous programmez, vous vous êtes peut-être déjà arraché les cheveux devant des problèmes de mauvais encodages. Mon expérience m'a montré que le mieux est encore d'aller à la source et de corriger directement le mauvais caractère (par exemple dans une page html) au lieu de tenter de le convertir/corriger.
Je vous donne tout de même quelques commandes pratiques en Python pour jouer avec les caractères unicode :smile:

Définissons un caractère s dont la valeur est "é" et observons son type :
>>> s='é'
>>> type(s), repr(s)
(<type 'str'>, "'\\xc3\\xa9'")

s est un caractère "brut" : c'est un type 'str' et non unicode. On voit toutefois qu'il est codé sur deux octets, il est donc bien au format UTF-8 mais n'offre pas les avantages de la classe unicode.
Transformons ce caratère au type unicode :
>>> u=unicode(s,"UTF-8")
>>> type(u), repr(u)
(<type 'unicode'>, "u'\\xe9'")

Le caractère unicode auquel on a à faire est donc le U+00E9.
Renseignons nous sur ce caractère :
>>> import unicodedata
>>> unicodedata.name(u)
'LATIN SMALL LETTER E WITH ACUTE'
>>> unicodedata.lookup('LATIN SMALL LETTER E WITH ACUTE')
u'\xe9'

Le type python unicode ne permet pas de tout faire, on pourrait le qualifier de "virtuel". On est obligé de le mettre en "dur" (l'encoder) pour effectuer certaines opérations comme écrire dans un fichier.
>>> u.encode("UTF-8")
'\xc3\xa9'

D'autres commandes pratiques :
>>> ord(u)
233
>>> unichr(233)
u'\xe9'
>>> u.encode('ascii', 'xmlcharrefreplace')
'é'

UTF-8 et stéganographie

L'idée d'utiliser l'unicode pour dissimuler des données m'est venue en me demandant s'il y avait pas plusieurs façons d'encoder le même caractère :idea: Après tout, chaque format (ASCII, UTF-8, UTF-16...) offre différents encodages pour un même caractère alors pourquoi pas le même caractère dans un même format ? Avec deux encodages possibles on peut donc glisser un bit (valeur 0 pour un encodage, valeur 1 pour le second).
Mes recherches sur Internet m'ont montré que non seulement je n'étais pas le seul à y avoir pensé mais en plus certains l'avaient déjà implémenté. Je n'invente donc rien mais je vous fournis les techniques utilisées.

La première technique est proposée par MockingEye et son implémentation unisteg.py.
Elle se base sur les diacritiques. Typiquement ce sont les accents et cédilles qui peuvent être attachés à un caractère.

Si vous vous rendez sur le bloc des diacritiques sur decodeunicode.org, vous verrez tout de suite de quoi je veux parler :smile:
Unicode permet donc d'encoder de deux façons différentes nos lettres à accent. Soit sous leur forme fixe (le "é") soit sous une forme combinée (la lettre "e" combinée avec le diacritique de l'accent aigue).
Le passage de la forme composée à la forme décomposée (et vice-versa) peut se faire par la fonction normalize de la librairie unicodedata en python :
>>> unicodedata.normalize("NFD",u)
u'e\u0301'
>>> unicodedata.normalize("NFC",u'e\u0301')
u'\xe9'
>>> unicodedata.normalize("NFD",u).encode("UTF-8")
'e\xcc\x81'

On remarque que le diacritique ne précéde pas le caractère mais le suit. Pour faire simple :
e combining diacritical

La seconde méthode est proposée par Antonio Alcorn. Elle est implémentée en PHP mais le code source n'est pas disponible. Toutefois en analysant le résultat on se rend compte que la technique se base sur l'utilisation de caractères différents mais visuellement très proche.
Par exemple, notre "e" est très proche du petit IE cyrillique.
Les caractères cyrilliques sont plus bruts que nos caractères et sont généralement représentés sans serif (voir empattement). En fonction de la police utilisée pour afficher les caractères, on ne verra donc pas la différence. On se servira pour ce faire d'une police sans-serif comme Arial.
Dans le second texte au début de cet article, vous avez peut-être remarqué que le "h" de "has" était plus large. C'est tout simplement parce qu'il s'agit du caractère cyrillique SHHA (U+04BA).

Ayant créé moi même mes outils de stéganographie UTF-8 (voir çi-dessous), la recherche des caractères similaires m'a pris un bon moment. J'ai rassemblé ça dans ce fichier.
Les caractères où la différence n'est pas visible (avec la bonne police) sont placés directement. Ceux où l'on peut se laisser prendre sont entre parenthèses avec le signe + accolé. Ceux entre parenthèses ressemblent d'assez loin.

utf8hide et utf8reveal

utf8hide.py permet comme son nom l'indique de cacher des données dans un texte.
Il demande deux arguments : le fichier dont il faut cacher le contenu et un fichier texte au format ISO-8859-1 au ASCII. Un troisème argument ("html") peut être passé si on souhaite ensuite injecter le résultat dans une page web.
J'ai repris l'idée de l'implémentation PHP qui propose d'utiliser seulement 5 bits pour coder un caractère à cacher en la poussant plus loin et sans les limitations.
Le programme fait une analyse du fichier à dissimuler et détermine le plus petit nombre de bits nécessaire pour coder un octet. Si le message secret est court, il défini un charset (alphabet) lui permettant ainsi de "comprimer" un octet sur seulement quelques bits (3, 4, 5, 6). Au-delà, le charset serait trop gros et le programme préfère utiliser les codes habituels des caractères.

Le résultat obtenu est placé dans le fichier out.txt. L'affichage donne le nombre de bits pour un octet (nbit), le charset utilisé et la taille du fichier secret. Il faut conserver ces paramêtres pour l'opération inverse.

Un peu à l'instar de ThumbStego qui nécessitait une image et sa signature, utf8reveal.py a besoin du texte ascii/iso8859 qui a servi à dissimuler le fichier et la version UTF-8 dans laquelle sont cachées les données.
On lui passe aussi en argument les variables vues plus tôt et le programme recréé le fichier secret dans "secret.xxx".

Les deux programmes affichent les bits à l'écran (0 ou 1) ce qui peut-être ennuyeux pour les gros fichiers... mais une telle utilisation est à éviter.
En effet, le programme a beau compresser comme il peut les données en entrées et utiliser la méthode des diacritiques ainsi que celle des ressemblances entre caractères, tous les caractères ne sont malheureusement pas exploitables. Le programme passe alors aux caractères suivant jusqu'à tomber sur un caractère exploitable. Le ratio est donc bien plus faible que 1/8ème mais c'est suffisant pour y passer quelques mots :smile:

Arghhh

J'ai eu la peur de ma vie (c'est quelque peu exagéré) en développant le code. En voulant recopier mes scripts vers un répertoire de sauvegarde, j'ai bêtement tapé "rm -r" au lieu de "cp", supprimant ainsi les codes et le répertoire de sauvegarde :cry:
A défaut de faire n'importe quoi, je me suis félicité d'avoir quelques connaissances en inforensique, ce qui m'a permis d'extraire le code de la partition :D Pourtant comme le code fait plus de 4096 octets, il était sur deux blocs mémoire et sur du ext3... merci à grep, dd et hexdump :rolleyes:

Python Opera Cache Dumper

, , , ...

Après le cookie dumper, voici le "cache dumper" qui comme son nom l'indique permet d'analyser le cache du navigateur Opera.

Sous Opera, on trouve deux dossiers de cache.
L'un s'appelle "opcache" et sert uniquement aux sites liés à Opera lui-même comme les requêtes à destination du "sitecheck" (système anti-fishing du navigateur), les requêtes vers DragonFly (API pour développeurs web intégré au navigateur) et requêtes vers les autres sous-domaines d'Opera.
Le second dossier est le dossier "cache4" et conserve la grande majorité des fichiers gardés en mémoire par Opera.

Dans les deux cas, les fichiers mis en cache sont renommés sous la forme oprXXXXX (où "XXXXX" est composé de chiffres et lettres majuscules) et un fichier nommé "dcache4.url" présent dans le même dossier est un index qui garde les informations spécifiques à chacun des fichiers.

Il est important de noter que si vous avez coché "Empty on exit" dans les préférences, Opera n'utilisera pas le fichier d'index mais stockera tout de même des fichiers en cache. Les associations entre les fichiers présents dans le cache et les sites Internet correspondants sont alors impossible à déterminer (Opera garde ces associations en mémoire mais ne les écrit pas sur le disque).

Comme pour l'analyse du fichier cookies4.dat la dernière fois, j'ai rencontré certains tags non documentés dans la documentation officielle.
On peut par exemple trouver le tag 0x00 dont la valeur est toujours la même (0x8000000B) et qui ne semble pas avoir de signification :confused:
Il y a un tag 0x2e qui représente la langue utilisée pour un fichier de cache donné (par exemple "fr_FR").
Tout aussi énigmatique, le tag 0x3a qui me semble lié à l'entête HTTP "Age" reçu comme réponse des serveurs. Un entête qui m'était inconnu et qui m'a fait penser au ver Conficker qui se base sur un autre entête HTTP pour déterminer la date et l'heure actuelle. Le header "Age" semble renvoyer une valeur numérique dans une intervalle prédéfinie et augmente avec le temps... ça pourrait être pratique comme moyen de trouver un nombre aléatoire :idea:

Enfin on trouve des tags qui permettent au navigateur d'intégrer directement des entêtes HTTP et leurs valeurs dans l'index de cache. Le tag racine est le 0x3b, suivi par le 0x3c. Le 0x3d défini le nom de l'entête et le tag 0x3e sa valeur.

Le programme que j'ai fait prend comme argument le chemin vers le fichier dcache4.url ainsi qu'un dossier où sera placé l'analyse du cache. Si ce dernier dossier n'existe pas, il est créé automatiquement.
Pour chaque fichier référencé dans le cache, le programme détermine sa nature à partir de sa valeur "mime" (image/png, text/html, application/x-javascript, etc) et s'il est compressé ("Content-Encoding" défini par le tag 0x20). Si c'est le cas, le fichier est décompressé (si possible car certains fichiers sont compressés en deflate et non par gzip :worried: ) avant d'être copiée dans le dossier de destination.
Le programme génère ensuite un fichier HTML qui permet d'afficher facilement l'ensemble des fichiers du cache et leurs métadonnées associées. S'il s'agit d'une image, elle est affichée. Sinon un lien permet d'accèder à la ressource. Les javascripts et codes html ont l'extension txt pour éviter qu'ils soient interprétés.

Comme les descriptions et les images sont chargées dans la même page HTML, ça peut prendre du temps à charger en fonction du cache analysé (il faut mieux un système avec une bonne mémoire p: )
Le résultat ressemble à ça (extrait) :

Le code est ici : opcadump.py penguin

Python Opera Cookie Dumper

, , , ...

Je me suis intéressé au format de fichier utilisé par le navigateur Opera.
Bien que les spécifications soient disponibles, on trouve peu d'outils pour gérer les historiques, caches et cookies du navigateur :worried:
Finalement je suis parvenu à écrire un script Python qui extrait les données du fichier cookies4.dat et les affiche dans un format texte plus conpréhensible que le format binaire d'Opera.
La sortie générée ressemble à ça :
Opera Cookie Dumper
File version: 1.0
Application version: 2.1
Cookie file
Size of idtags: 1 bytes
Size of payload length fields: 2 bytes
MSB: 0x80
===================================
dsource.org
        dsource-auth_data  = a%3A11%3A%22autologinid%22%3Bs%3A6%3A%22userid%22%3Bi%3A-1%7D
        path = /projects
        path = /dsss
        trac_session  = e7f77d380bc7290b2347490c
        path = /tutorials
        trac_session  = 49ca56cec7f142d58d2201ea
userfriendly.org
        __qca  = 1239814048-45958653-24014683
...

Toutes les informations n'apparaissent pas. Actuellement il n'est affiché que le domaine, le path sur le serveur et les noms et valeurs des cookies.

Durant mes recherches j'ai découvert un tag non documenté (tag id 0x26) qui correspond en réalité au champ "Delete new cookies when exiting Opera is checked" dans les préférences de site. Si la valeur est à 2 cela signifie que la suppression est activée. Si la valeur est à 1 ou si le tag est omis cela signifie que la suppression n'a pas lieu.
Il y a aussi un flag 0x27|MSB que j'ai rencontré mais je n'ai pas pû découvrir sa signification :confused:

Dans tous les cas ça peut être utile pour faire du Web Browser Forensics et le code est disponible ici :
opcodump.py penguin

Nouvelle version de Wapiti

, , , ...

Comme promis précédemment, une nouvelle version stable de Wapiti est disponible au téléchargements dans différents formats d'archivage (toujours l'appréhension de merder en les faisant alors j'ai vérifié à deux fois p: )

Peu de changements depuis le dernier post sur le sujet et sa version SVN correspondante mais ça vaut quand même le coup de se mettre à jour puisque j'ai rajouté quelques "patterns" pour la détection de failles PHP et modifié les utilitaires cookie.py et getcookie.py pour qu'ils fonctionnent sur les applications web qui s'entêteraient à gérer les entête HTTP de façon peut conventionnelle.

D'ailleurs je devrais remercier au passage les auteurs des applis my little forum (juste un petit XSS) et iDB (une petite inclusion locale à l'exploitation limitée) sur lesquels j'effectuais mes tests en plus des petits scripts que j'ai fait à l'occasion :smile:

Maintenant il va falloir que je mette le site web à jour :whistle:

Télécharger Wapiti sur SourceForge.net

Mon langage de programmation idéal

, , , ...

Un billet sérieux en cette journée du 1er avril... :whistle:

Une question me trotte dans la tête depuis quelques temps : quel est mon langage de programmation idéal, celui qui me conviendra le mieux, qui me transformera en ninja du code ? :ninja:

J'y ai réfléchi et j'ai finalement noté les caractéristiques qu'il devrait avoir :
  • Il est multi-paradigme impératif et objet
  • Il a un typage statique fort
  • Il a des types entier pratique (du style uint, ulong) comme C#
  • Il se compile en langage machine
  • Il est multiplate-forme ou facilement portable
  • Il a un système de gestion de la mémoire, comme un garbage collector
  • Il a des types de base évolués (listes et dictionnaires comme en Python) et permet d'obtenir rapidement des résultats, c'est un langage de haut niveau
  • Il permet toutefois d'interagir avec le système comme c'est possible sous Linux en C
  • Il a une syntaxe proche du C (avec des accolades)
  • Ce n'est pas du Perl
  • Il a une API riche comme Java
  • Il a une ou des bibliothèques permettant de réaliser des interfaces graphiques

Il faut avouer qu'au début, c'était plutôt mal parti pour trouver un tel langage de programmation...
Mes recherches m'ont amené à jeter un oeil à différents langages :
  • C# : correspond pour de nombreux points, multiplate-forme, framework .NET fréquent sous Windows mais Mono rare sous Linux. Ca reste toutefois du bytecode.
  • Objective Caml a pas mal de points qui collent aussi... mais la syntaxe ne m'attire pas
  • C++ : je n'en ai pas forcément de bons souvenirs (pas de gestion de la mémoire avancé, me semblait casse-tête et brouillon) mais peut-être je devrais lui redonner une chance p: En ajoutant une couche supplémentaire (comme les libs Qt) on obtient un résultat plus proche de mes attentes. La version C++0x pourrait valoir le coup.
  • D semble avoir tout ce que je souhaite, même si il y a encore peu de librairies et de documentation dans ce langage

J'ai donc testé le D, réussi à faire des programmes de base (basé sur sa librairie standard). La compilation d'un Hello World donne un exécutable assez lourd cow mais cela peut se compenser avec le temps gagné sur de plus grosses applications...
Mais je me suis alors rendu compte qu'il manque un point : la facilité de mise en place des outils pour programmer p: J'ai beau me battre pour tenter d'installer et d'utiliser GtkD, je n'ai obenu aucun résultat satisfaisant...
Je vais peut-être devoir me remettre au C++ :confused:

Et vous, quelles sont les caractéristiques de votre langage de programmation idéal ?

Awesome !!

, , , ...

Après une semaine à me concentrer sur le développement de Wapiti, j'ai mis à jour les ChangeLog de Wapiti et lswww et j'en ai profité pour rectifier le fichier README.

Je me suis alors rendu compte du travail effectué depuis la version 2.0.0 béta et aussi que je ne vous en ait parlé que très récemment et sans réelles explications :eyes: (même si j'avais donné quelques infos en commentaire sur la dernière béta :left: ).

Le moment est donc venu de vous tenir au courant de ce que la prochaine version à venir apportera et à quoi vous attendre :wink:
Tout d'abord la version 2.0.0-béta ne verra pas sa version stable. En effet il y a eu tellement de changement qu'il ne s'agit plus du tout de la même version :ko:
Cette version apportait tout de même son lot de nouveautés comme une nouvelle technique de scan pour les XSS, la génération de rapports de scans, l'ajout d'option --nice évitant les boucles infinies lors des scans et la correction de l'authentification HTTP.

Le changement radical qui s'est effectué est avant tout l'abandon de la librairie urllib2 pour httplib2, petite librairie basée sur httplib et sous licence MIT.
Le grand avantage de ce changement, c'est le support des connexions HTTP persistantes par httplib2. Alors que les anciennes versions de Wapiti basées sur urllib2 pouvait avoir un effet néfaste (saturation du nombre de connexions du serveur web :eek: ), ici le maximum de requêtes possible sera envoyé à travers une même connexion. Non seulement le serveur ne se fatigue pas mais en plus on obtient un gain important en vitesse de scan :ninja:
Bien sûr l'intégration de cette librairie ne s'est pas faite sans quelques nouveaux bugs qui ont fait leur apparition mais ils ont pû être corrigés.
L'une des premières conséquence a été la perte du support des proxies. Pour moi il semblait évident que httplib2 supporait les proxies HTTP "standards"... ce n'était pas le cas nervous
Il a donc fallu modifier cette librairie et aussi permettre l'intégration de toutes les bonnes choses qui étaient offertes.

Au final on a du nouveau sur les proxies avec le support des proxies HTTP, SOCKS v4, SOCKS v5 (passage à travers Tor) ou tunneling par HTTP CONNECT :yes:
Je n'ai pas eu l'occastion de tester cette dernière mais pour les proxies SOCKS ça fonctionne :happy:

On a ensuite croisé des soucis avec les entêtes et codes d'erreurs HTTP ainsi que les redirections traitées de façon invisible par la librairie. Comme Wapiti essaye de déclencher des erreurs dans les pages, httplib2 n'a pas forcément apprécié et on lui a retiré le support des redirections pour le laisser à Wapiti qui faisait ça très bien.

Pour terminer sur les bugs bug , j'ai rajouté des vérifications sur les timeouts dans les différents modules et cloturé la quasi-totalité des bugs rapportés sur le tracker.

J'ai rajouté une nouvelle option à lswww : -e (ou --export) qui permet de générer un fichier XML des urls et des formulaires trouvés durant un scan. Pour l'instant cette option n'a aucune utilité mais j'espère que d'autres logiciels intégreront une option pour importer ces données (à l'occasion j'en toucherais quelques mots aux développeurs de sqlmap :smile: )

Les attaques SQL ne sont d'ailleurs pas en reste puisque le scan des failles d'injection SQL en aveugle ("time-based") a été ajouté. Je vous invite à jeter un oeil aux payloads utilisés :sherlock:

Restez dans les parages pour être tenu au courant de la sortie de cette prochaine version (encore des vérifications à faire).
Les plus impatients peuvent déjà récupérer la version présente sur le SVN :
svn co https://wapiti.svn.sourceforge.net/svnroot/wapiti/trunk wapiti

Et pendant que j'y pense, Wapiti a été intégré au Live-CD OWASP 2008 :cool: