Skip navigation.

devloop :: blog

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

Posts tagged with "urllib2"

Wapiti 2.0.0 Béta

, , , ...

Alors que Wapiti a dépassé doucement mais surement la barre des 16200 téléchargements sur SourceForge, les plus observateurs auront remarqué la sortie d'une version 2.0.0 béta avant-hier soir.

La question que vous vous posez certainement c'est comment l'on peut passer d'une version 1.1.7-alpha à une version 2.0.0-béta...
Tout simplement avec beaucoup de changements !! Et il s'en est passé des choses depuis la sortie de la précédente version.

Premièrement, le nombre de développeurs est passé de 1 à 3 grace à l'aide de 2 développeurs espagnols de ICT-Romulus.
Leur souhait était de pouvoir apporter des nouvelles fonctionnalités à Wapiti, notamment pour faciliter son intégration dans un projet de framework J2EE basé sur Maven (si j'ai tout compris lol).
Dans tous les cas ils ont proposé de participer au développement de Wapiti afin que tout les utilisateurs puissent profiter de leurs idées et de leurs modifications :smile: Cela est passé par la mise en place d'un espace SVN pour le projet pour faciliter le développement.

Leur objectif principal était de travailler sur le rendu final fournit par Wapiti. Ainsi il est possible d'obtenir un compte rendu des vulnérabilités dans 3 formats différents : XML, HTML et texte simple. Pour cela les options -f (format) et -o (output) ont été rajoutés.
Ils ont aussi réussi à séparer les payloads du code, ce qui rend plus simple leur ajout. Le code a été aussi revu et est plus modulaire.
Des règles de détection pour les failles SQL ont aussi été rajoutées.

De mon côté j'ai pû enfin résoudre le problème des boucles sans fin lors du scan d'urls en ajoutant l'option -n (ou --nice) qui permet de définir un "seuil de tolérance" au niveau des urls du même type.
Ainsi si les pages suivantes ont déjà été scannées :
http://server/p?a=x&b=1&c=x
http://server/p?a=x&b=2&c=x
http://server/p?a=x&b=2&c=y

Avec un seuil de 2, quand l'url "http://server/p?a=x&b=3&c=x" sera trouvée, elle sera exclue car déjà 2 urls du même pattern ont déjà été trouvées (http://server/p?a=x&b=*&c=x).
Même chose avec l'url http://server/p?a=x&b=2&c=z.
Par défaut aucun seuil n'est spécifié (ce qui revient à le fixer à 0). A vous de voir la valeur qui vous semble juste (10 me parait en bon compromis pour faire beaucoup de possibilités sans tourner en boucle).

J'ai aussi réussi à faire fonctionner l'authentification HTTP (option -a) en pompant sur le code de sqlmap. Même si les instructions sont sensiblement différentes par rapport à ce que Wapiti faisait, le principe est le même et je ne saurais pas dire pourquoi ça ne fonctionnait pas auparavant (alors que proxies et cookies fonctionnaient)... un des mystères de Python :left:
Malheureusement, étant donné la façon dont les modules urllib2 fonctionnent, il est préférable de retirer l'authentification sur le serveur et d'utiliser Wapiti simplement. En effet pour chaque url, si l'authentification est présente, Python va émettre deux requêtes : une première sans authentification qui va renvoyer une erreur 401. Et une seconde avec les identifiants pour passer la vérification :left:

Enfin la nouvelle méthode de scan XSS est complètement implémentée et la librairie Beautiful Soup a été mis à jour.

Pour la prochaine version, différents changements sont à faire comme pouvoir gérer les erreurs HTTP 500 (nouveau bug), améliorer la qualité des rapports de scan, limiter le nombre de plantages liés au décodage Unicode :frown: et enfin travailler sur la vitesse de scan de Wapiti.
En effet lors de certains tests, on s'apperçoit que Wapiti peut avoir un effet DoS sur le serveur web (voir que les 152 process lancés par Apache pour répondre aux requêtes sont tous occupés c'est pas top...) Il faut donc essayer d'envoyer le plus de requêtes possibles par connexion (ou trouver la juste proportion entre les deux)

Dans tous les cas, je ne peux que vous conseiller de passer à cette nouvelle version qui apporte des fonctionnalités importantes :smile:

Télécharger Wapiti-2.0.0-béta.

Anywhere.FM Python CLI Player

, , , ...

C'est après pas mal de recherches et de tests de code que je suis finalement parvenu à développer en Python un lecteur de ma musique présente sur le site Anywhere.FM :smile:

Le dernier bug rencontré était, comme expliqué dans un précédent, le décodage de certaines chaines de caractères qui ne respectaient pas le format UTF-8. Le responsable était finalement le site lui-même ou plutôt les utilisateurs qui envoit des données au serveur à l'aide d'un navigateur utilisant un autre encodage.

Ainsi dans mon cas, le décodage de mon profil échouait car dans les données retournées se trouvait entre autres le nom mal encodé Ted Gärdestad correspondant à l'un des artistes les plus écoutés par une personne dans ma liste d'amis (la fonctione RPC get_complete_profiles du site renvoie beaucoup d'infos superflues :-| )

Pour résoudre ce souci il fallait intervenir sur la méthode readString de la classe Decoder de PyAMF (module amf3).
Comme je ne voulais pas et d'ailleurs ne pouvais pas modifier le code de PyAMF (installé sous forme de "egg" sur mon système), j'ai plutôt imaginé une technique de "Python API Hooking".
En fait il s'agit simplement de la redéfinition puis d'un écrasement d'une méthode d'une classe Python... mais avouez que dit comme ça, ça en jette beaucoup moins p:

La vérification ajoutée à la méthode readString consistait à lever une exception si le passage en unicode échouait et dans ce cas, à remplacer les mauvais caractères par des underscore. Ce qui donnait :
from pyamf.amf3 import Decoder
from string import maketrans

in_string="".join([chr(i) for i in range(126,256)])
out_string="_"*130
trans=maketrans(in_string,out_string)

def my_readString(object, use_references=True):
  def readLength():
      x = object.readUnsignedInteger()

      return (x >> 1, x & 1 == 0)

  length, is_reference = readLength()

  if use_references and is_reference:
      return object.context.getString(length)

  buf = object.stream.read(length)

  try:
    result = unicode(buf, "utf8")
  except UnicodeDecodeError:
    buf=buf.translate(trans)
    result = unicode(buf, "utf8")

  if len(result) != 0 and use_references:
      object.context.addString(result)

  return result

sav_readString=Decoder.readString
Decoder.readString=my_readString

L'opération de récupération et de correction de la liste de lecture "Entire Library" pouvant prendre un certain temps si la liste de lecture est importante, j'ai préféré diviser le programme en deux : le premier code récupère la liste de lecture et l'enregistre sous forme d'une liste Python dans un fichier ; le second est le lecteur qui charge la liste de lecture et va lire de façon aléatoire et unique un titre de la bibliothèque :smile:
Au final on gagne largement en charge réseau et en temps d'accès par rapport à l'utilisation du site Internet et on n'a pas à subir les utilisations mémoire et processeur gourmandes du plugin Flash p:

Vous avez donc get_library.py qui donne un résultat de ce style :
Connection on the server...
Connexion successfull!
user_id = 5418
Hooking the PyAMF Decoder
Getting the Entire Library playlist...
Library dumped!

qui génère un fichier library.py utilisé par le lecteur player.py qui joue les flux musicaux et donne un affichage dans ce genre :
Connecting on the server...
Connexion successfull
user_id = 5418
White America - Eminem ( The Eminem Show )
Troisième tour - Rapaces ( 2000 )
Les Poubelles du Coeur - Parabellum ( 1984-2004 )
Question de fun - Les Shériff ( La Saga Des Sheriff (disc 2) )
Alcohol - Dropkick Murphys ( Live On St. Patrick's Day )
Marilyn Moore - Sonic Youth ( Evol )
Come Back, Baby - Ramones ( The Chrysalis Years (disc 1) )
The Watcher - Dr. Dre ( 2001 )
...

La partie lecteur nécessite la présence de mplayer sur le système. Seul regret : on ne peut pas trop jouer sur l'interface de mplayer pour avoir quelque chose de moins verbeux et agréable... une simple barre de défilement de la lecture en cours (à l'instar de wget) m'aurait bien plu... mais c'est une autre histoire :smile:

Lire directement la musique de Anywhere.FM : ça marche (presque)

, , , ...

Suite de ma précédente étude du fonctionnement de Anywhere.FM.

Je me suis lancé aujourd'hui dans la "pratique" en écrivant quelques lignes de code et les résultats sont pour le moins encourageants :smile:
Je me suis orienté naturellement vers les modules urllib2 et cookielib de Python que j'avais utilisé pour Wapiti.

Les premières étapes se sont réalisées sans problème (envoies de données par GET ou POST, utilisation d'une "boîte à cookies" p: )
Pour la seconde étape j'avais le choix entre utiliser les capacitées de PyAMF à effectuer les requêtes mais en devant injecter mes entêtes HTTP ou rester sur l'utilisation du module urllib2 et injecter les données encodées à l'aide de PyAMF.
J'ai finalement opté pour la seconde méthode, même s'il m'a fallu un peu de temps pour comprendre quels arguments passer à quelles fonctions. Pour résumer j'utilise seulement les fonctionnalitées de création d'objet (plus propre) et d'encodeur/décodeur de PyAMF et toute la partie communication est réalisée par urllib2.

J'ai d'abord implémenté les étapes que j'avais observé au complet puis j'ai ensuite commenté certaines étapes dont l'utilité était douteuse.
Au final les réponses aux questions précédentes sont :
  • _unique_request_id_ est aléatoire. On peut même le définir nous même au début. Reprendre la même valeur à chaque nouvelle session ne semble pas poser de problème, même sur des intervalles de temps rapprochés. Je n'ai pas vérifié si on pouvait se passer de l'incrémentation d'une requête à une autre
  • Les fameuses variabes __qca et __qcb définies par le biais du Javascript sur le serveur quantserve semblent totalement superflues. Ne pas les utiliser n'entrave en rien la communication avec Anywhere.FM. De toute évidence elles sont utilisées uniquement à des fins de tracking
  • tracker_id n'a pas d'utilité, malgré qu'il soit explicitement défini (une requête est générée uniquement à cet effet). Il pourrait s'agir d'une fonctionnalitée que les administrateurs n'ont pas encore pû implémenté mais à venir ?!
  • Certains arguments passés à get_songs_for_user_playlists restent un mystère, toutefois on n'a pas besoin d'en savoir plus pour accèder à la librairie complète d'un utilisateur

Le code que vous pourrez trouver ici : PyAnywhereFM.py et sur pastebin.com n'est pas totalement fonctionnel.
En effet si on parvient bien à ouvrir une session sur le site, à effectuer des requêtes AMF et obtenir les résultats, on ne parvientpas pour le moment à décoder les réponses AMF à cause d'erreurs de décodage UTF-8. A l'heure actuelle je ne saurais pas dire si le problème vient de Anywhere.FM, de PyAMF ou encore de Python...

Il est tout de même possible d'obtenir un jeton valide pour accèder à un titre dont on connait par avance le "master_id" et le "song_ressource_id" (paramêtres qui sont fixes).
Le code tente de se connecter avec les identifiants présents dans la source (à vous d'y insérer les votres) ou fonctionnera avec l'utilisateur par défaut (démo, id = 89 comme vu la dernière fois) si les identifiants sont invalides. Il va ensuite lire un titre dans ma librairie à l'aide de mplayer.

Vous pouvez utiliser un sniffeur comme Wireshark pour comprendre ce qui se passe en fond lors de l'utilisation du script. Il faut noter toutefois que l'utilisateur "demo" a une librairie vide, c'est pour cela qu'il est possible de décommenter une ligne fixant le user_id à 46 (correspondant au compte "Free Music")

L'étape restante consiste donc à extraire les données des réponses AMF obtenues, ce qui ne devrait pas être trop difficile puisque le "master_id" et le "song_ressource_id" sont envoyés comme des chaines de caractères et non comme des entiers.
Tout cela montre qu'il est assez aisé (le code fait 129 lignes une fois les commentaires et les lignes vides retirées) de télécharger de la musique sur Anywhere.FM et malgré qu'il n'y ait pas de système permettant de rechercher un titre en particulier, il serait possible de générer une base de données des titres disponibles en récupérant les profils puis les listes de lecture des utilisateurs du site. Evidemment ça prendrait du temps, mais ce serait toujours plus rapide que de fouiller par le biais de l'interface web du site p:

ZoomifyHack

, , , ...

J'étais désespérément (j'exagère quelque peu) à la recherche d'un fond d'écran ayant pour thème Les Annales du Disque-monde de Terry Pratchett quand je suis tombé sur cette peinture qui m'a sauté aux yeux :smile:
Malheureusement aucun lien vers l'image complète sur le site en question, seulement une applet Flash qui permet de se déplacer et de zoomer dans l'image.
J'ai donc décidé d'étudier le fonctionnement de Zoomify, l'applet utilisée sur le site, pour tenter de retrouver l'url de l'image complète :smile:

Après avoir analysé le traffic web avec Wireshark, force est de constater que l'image est découpée en morceaux de petite taille. C'est l'applet qui se charge de les afficher ressoudées.

J'ai codé un petit script python baptisé ZoomifyHack qui à partir de la page où se trouve l'applet, va retrouver les images pour les recoller en un unique morceau.

Les opérations effectuées par le script sont les suivantes et vous permettront de comprendre le fonctionnement de l'applet :
  1. Retrouver la balise "object" dans la page web où se trouve le flash
  2. Lire les sous-balises "param" et trouver celle identifiée comme "FlashVars"
  3. Analyser le champ "value" de cette sous-balise pour en extraire la valeur de la variable "zoomifyImagePath" (les variables et leurs valeurs sont "urlencodées")
  4. Lire dans ce path, le contenu du fichier "ImageProperties.xml" qui contient des informations sur l'image : largeur (width), hauteur (height) et taille des morceaux carrés qui constituent l'image complète (tilesize))
  5. Calculer en combien de morceaux se décompose l'image en largeur et hauteur par un calcul simple
  6. Retrouver par force brute sur les urls le ratio correspondant à l'image complète. Les fichiers composant l'image découpés sont nommés sur le modèle <ratio>-<indice_horizontal>-<indice_vertical>.jpg
  7. Créer un répertoire temporaire et se placer dedans
  8. Télécharger ces images sachant qu'elles se trouvent dans des sous-dossiers du path indiqué par "zoomifyImagePath" et qui suivent le modèle TileGroupX ou X est un chiffre dont je n'ai pas encore déterminé l'origine (mais commençant à 0 puis s'incrémentant selon le nombre d'images)
  9. Recoller les morceaux à l'aide de la commande "convert" (package ImageMagick) en un fichier baptisé "original.jpg"

Pour faire fonctionner le script il faut Beautiful Soup (télécharger le fichier python et le placer dans le même dossier que ZoomifyHack.py) et convert (package ImageMagick).

Il y a quelques urls de pages utilisant Zoomify présentes dans le code source pour ceux qui souhaitent faire des tests.
Au final j'ai pû avoir mon fond d'écran p:

ZoomifyHack.py

Wapiti 1.1.6

, , , ...

Je viens de mettre en ligne une nouvelle version de Wapiti.
Les changements apportés concernent uniquement lswww (la partie chargée de l'exploration des sites Internet).

Les anciennes versions se basaient sur l'extension d'un fichier et ensuite sur son contenu (tel que déclaré par le serveur web) pour déterminer s'il s'agissait d'une page web (donc potentiellement exploitable).
Maintenant lswww compte principalement sur le Content-Type, ce qui fait qu'il peut dorénavant attaquer des scripts avec des extensions plus exotiques.
Exemple avec un site utilisant mod_python :

python lswww.py http://www.csb.sunysb.edu/bsb/
...........................
+ URLs :
http://www.csb.sunysb.edu/bsb/
http://www.csb.sunysb.edu/bsb/formdata.py
http://www.csb.sunysb.edu/bsb/images/X26C.jpg
http://www.csb.sunysb.edu/bsb/images/lnxcluster.jpg
http://www.csb.sunysb.edu/bsb/images/nmr_spect.jpg
http://www.csb.sunysb.edu/bsb/images/rigaku.jpg
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=A
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=B
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=C
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=D
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=E
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=F
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=G
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=H
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=I
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=J
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=K
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=L
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=admission
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=contact
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=courses
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=degreereq
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=facilities
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=faculty
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=facultyres
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=home
http://www.csb.sunysb.edu/bsb/mkpage.py?fref=onapply

+ Forms Info :
From: http://www.csb.sunysb.edu/bsb/mkpage.py?fref=contact
To: http://www.csb.sunysb.edu/bsb/formdata.py
        note : on
        name : on
        email : on

BeautifulSoup a été rajouté au package. lswww s'en sert pour nettoyer les pages web avant de les étudier dans le cas où uTidyLib n'est pas présent sur le système. C'est moins puissant que Tidy mais ça permet au moins de fermer les balises restées ouvertes.
L'objectif de cet ajout est de rendre lswww et Wapiti plus performant "out of the box" (sans installation de modules supplémentaires)

Et dans le cas où ni uTidyLib ni BeautifulSoup ne sont présent, une petite expression régulière pourra prendre le relais :smile:

Des modifications ont aussi été faites pour que le logiciel fonctionne si cookielib n'est pas installé. Par contre les options pour les cookies n'auront plus effet.

Télécharger Wapiti 1.1.6

Wapiti-1.1.5

, , , ...

Une nouvelle version vient d'être ajoutée sur Sourceforge.
Comme prévu ça ajoute le système d'exclusion par joker dont j'avais parlé.
Ca corrige aussi quelques bugs qui étaient apparus avec la version précédente, dont une au niveau de la gestion des urls dans lswww et deux erreurs au niveau de l'authentification HTTP (dont une erreur typographique).

Exemple d'utilisation des nouvelles possibilités d'exclusion avec lswww :
python lswww.py http://labs.google.com/ -x http://labs.google.com/p*
..........
+ URLs :
http://labs.google.com/
http://labs.google.com/accessible/
http://labs.google.com/accessible/advanced_search.html
http://labs.google.com/accessible/faq.html
http://labs.google.com/britney.html
http://labs.google.com/faq.html
http://labs.google.com/frooglewml.html
http://labs.google.com/intl/uk/frooglewml.html
http://labs.google.com/labsterms.html
http://labs.google.com/why-google.html

(sans exclusion on trouverait un tas de pages dans http://labs.google.com/papers/ et http://labs.google.com/people/ :wink: )
Evidemment on peut placer le joker n'importe où (sauf au tout début de l'url, réservé pour la vérification du protocole) et on peut l'utiliser plusieurs fois (par exemple -x http://labs.google.com/people/s*n*k/index.html )

Ceux qui ne sont intéressés que par lswww peuvent avoir la dernière version ici.

Les options proposées par Wapiti sont maintenant visibles sur wapiti.sourceforge.net.

Wapiti-1.1.4

, , , ...

Woohoo !!
Je viens de rendre disponible une nouvelle version de Wapiti, mon scanneur de vulnérabilités pour applications web :hat:
Pas de nouveautés dans les techniques d'attaques, les améliorations se sont portées uniquement sur la maniabilité du logiciel.

De nouvelles options ont fait leur apparition, principalement basées sur les demandes d'un utilisateur (même si je n'ai pas pû tout faire).
Parmis les nouvelles options communes à lswww et Wapiti il y a la possibilité de fixer le temps d'attente avant d'abandonner la lecture d'une page. Il suffit de passer le nombre de secondes avec -t (ou --timeout=). Ca peut être très utile pour augmenter le temps d'attente quand on a une mauvaise connexion ("56k old school style" :psmurf: ou utilisation d'un proxy).
Un message est aussi affiché par lswww quand le temps pour accèder à une page a excédé le temps spécifié (par défaut 6 secondes), c'est pratique pour détecter des erreurs dans un code (boucles infinies...)

Une option -v (--verbose) permet de rendre lswww et Wapiti plus ou moins verbeux. Pour Wapiti le niveau de verbosité par défaut est 0, ça correspond au comportement des précédentes versions. Le niveau 1 affiche l'url sur laquelle Wapiti est en train de travailler (celle trouvée lors de l'exploration du site). Le niveau 2 va plus loin en affichant les urls avec les payloads utilisés pour chaque attaque. Ce niveau est particulièrement verbeux, pratique si vous désirez signaler un bug bug

J'ai revu le code de l'application afin de la rendre plus modulaire. Désormais un jeu de fonctions permet de choisir les options pour l'attaque. On pourra par exemple se restreindre aux envois par GET (ou POST), ne chercher que des vulnérabilités de type XSS (ou autre) ou chercher uniquement les failles les plus sérieuses (inclusion de fichiers, exécution de commandes...)
L'objectif principal est de faire en sorte de faciliter le travail de ceux qui voudrait faire une interface (graphique ou non) pour Wapiti, ou intégrer Wapiti comme module pour leur application.

Pour l'instant les options en ligne de commande de Wapiti ne permettent pas de faire des choix aussi précis. L'option -m (ou --module) permet de choisir un groupement d'options par défaut. Wapiti accepte les possibilités suivantes :
GET_XSS : recherche uniquement les vulnérabilités XSS en n'envoyant les données que par GET
POST_XSS : pareil mais cette fois en utilisant seulement la méthode HTTP POST
GET_ALL : effectue toutes les catégories d'attaque en n'utilisant que la méthode GET

Des bugs ont été corrigés, comme celui dû à un entête Content-Type manquant ou encore l'impossibilité de récupérer un cookie sous Webmin.
J'ai fixé une erreur au niveau de la correction des urls dans lswww (un paramêtre interdit n'était pas détecté s'il était seul) ainsi que la gestion des erreurs 404.

Il me reste encore quelques trucs à faire comme exlure un dossier complet du scan et trouver un système de gestion des paramêtres intelligent (pour éviter que Wapiti tourne indéfiniment)

Je ne pense pas implémenter le support de SOCKS tant qu'aucun module simple à mettre en place ne sera disponible. Utilisez un proxy capable de rediriger les requêtes à la place (Privoxy ou même à coups de socat)
Voilà j'ai fait le tour.

Télécharger Wapiti-1.1.4 sur Sourceforge

Wapiti 1.1.2

, , , ...

Cette nouvelle version n'apporte pas de nouvelles fonctionnalités mais corrige deux bugs qui pouvaient être génant bug

Le premier pouvait amener l'application à crasher dans certains cas (quand l'envoi de données sur un formulaire renvoit un code d'erreur 500) et le second était une expression régulière imparfaite pour corriger les urls qui font des remontées dans l'arborescence.

Wapiti commence à faire parler de lui et s'est déjà fait linuxfr-er, stumbleupon-er, del.icio.us-er, blogmarks-er, kikuz0u-er et enfin darknet-er (oui ça fait beaucoup de verbes qui n'existent pas).
Il est même cité dans la page Wikipedia : XSS

Wapiti a dépassé la barre des 1000 téléchargements :up:

wapiti.sourceforge.net

Nouvelle version de Wapiti

, , , ...

Je viens de mettre en ligne une nouvelle version de Wapiti, mon scanneur de vulnérabilités pour applications web.
Cette version 1.1.0 téléchargeable sur SourceForge apporte un bon nombre d'améliorations et marque le passage à urllib2 (le module Python utilisé pour effectuer les requêtes HTTP).

Parmis les nouveautés il y a :
  • la détection des redirections HTTP
  • Le support des proxies HTTP dans Wapiti
  • Une gestion des cookies plus évoluée et plus simple d'utilisation
  • Détection des injections LDAP (pour PHP et Java)
  • Détection des injections de commandes (relatives à PHP, c'est à dire les fonctions eval, system, exec, passtrhu...)
  • Détection des injections CRLF (injections qui permettent de modifier les entêtes HTTP envoyés par le serveur)
  • Quelques améliorations au niveau des XSS et des injections SQL

Dans l'ancienne version l'option -c permettait de spécifier un identifiant de session à utiliser pour scanner l'application. Ce n'était pas très pratique, de plus certaines applications envoient plusieurs entêtes Set-Cookie ou utilisent un nombre important de paramêtres de session.
Avec cette nouvelle version on n'a plus à se soucier du fonctionnement interne de l'application et à connaître le nom des paramêtres à garder.

Le paramêtre à passer à l'option -c (ou --cookie) est dorénavant le nom d'un fichier texte dans lequel sera enregistré les paramêtres de sessions.
Comme pour les anciennes versions il faut utiliser les utilitaires getcookie.py ou cookie.py pour générer ce fichier cookie. On peut ensuite l'utiliser par wapiti, toujours avec la même option.

L'authentification HTTP (pour passer les htaccess), bien qu'intégrée dans Wapiti, ne fonctionne pas avec Python 2.4. Cela est dû au module HTTPBasicAuthHandler qui est trop buggé dans cette version. Ca marchera peut-être avec Python 2.5 mais je n'ai pas pû tester.

Le code de lswww a bien évidemment évolué lui aussi. L'objectif de cette librairie est de recenser toutes les pages et les formulaires trouvés sur un site donné. Le code devrait intéresser tous les développeurs qui se battent avec urllib2, surtout que tout n'est pas documenté. Vous le trouverez ici : lswww.py

Wapiti a été utilisé par Dokeos, une application web destiné au monde de l'éducation et des formations afin de détecter et corriger des failles XSS.

Je vous invite à tester Wapiti et à faire parler de lui :wink:

Wapiti 1.0.2

, , , ...

Une nouvelle version de Wapiti est disponible.
Wapiti est un scanneur de vulnérabilités pour applications Web. Son objectif est d'attaquer les pages dynamiques de l'application en envoyant des données malicieuses afin de détecter différentes failles de sécurité.

Cette version 1.0.2 peut détecter plus de vulnérabilités que les versions précédentes. Les failles relatives aux applications Java et les injections XPath font partie des nouveautés de cette version.

Quelques corrections de bug ont été faites dans la gestion des urls et des formulaires.
Les versions précédentes de Wapiti utilisaient la méthode HTTP POST pour chaque formulaire trouvé. Maintenant la méthode GET est utilisée si l'utilisation de POST n'est pas explicitée dans le code HTML. C'est le comportement par défaut décrit dans les spécifications HTML. Dans ce cas une URL est générée à partir des champs du formulaire.
Le type input search est maintenant reconnu par Wapiti.
Les scripts utilisant directement la QUERY_STRING comme variable sont dorénavant attaqués (les urls du type http://server/page?index).

L'affichage a aussi été amélioré pour être plus lisible et donne plus d'informations.
Pour les formulaires, Wapiti affiche maintenant l'url de la page où se trouvait le formulaire (en plus de la page qui reçoit les données ainsi que les champs et les valeurs utilisées pour l'attaque).
L'option -u affiche en rouge la variable fautive permettant ainsi de trouver au premier coup d'oeil où se trouve le problème. Cette option ne fonctionne que sous Unix.

Une autre option a fait son apparition : -r (ou --remove) permet de retirer certains paramêtres d'une URL. C'est très pratique pour éviter des systèmes de pagination qui peuvent faire tourner Wapiti indéfiniement ou pour ne pas prendre en compte des paramêtres relatifs à la mise en forme.

Enfin je tiens à préciser que cette version 1.0.2 est une version de compatibilité : je développe parallèlement une version utilisant urllib2 et qui sera dépendante de Python 2.4. J'ai donc décidé de faire profiter l'ancienne branche de développement en y ajoutant les fonctionnalitées que je pouvais faire passer.
La prochaine version proposera une gestion des cookies bien plus agréable, incluera le support des proxies dans Wapiti et sera capable de comprendre les redirections HTTP.

En attendant je vous invite à télécharger Wapiti-1.0.2

Tout autre sujet...
Depuis hier le blog subit des attaques sans précédent de robots spammeurs... mais le blog a tenu bon jusque-là :smile:
L'interface de Last.fm a été refaite... bôôô !!