Nel password cracking, una delle tecniche più utilizzate è l’attacco Brute Force (letteralmente “Forza Bruta”). In un attacco brute force, un attaccante prova tutte le possibili combinazioni di password fino a trovare quella corretta. Ad esempio, se la password è lunga 8 caratteri e l’attaccante usa un dataset di 62 caratteri (26 lettere maiuscole + 26 minuscole + 10 numeri), il numero totale di permutazioni è:
62^(8) = 218.340.105.584.896 (218 trilioni)
Un metodo basato perlopiù sulla fortuna che non ad un metodo vero e proprio; occorre quindi concentrare l’attacco in modo da ridurre notevolmente il numero di combinazioni ad esempio utilizzando un Attacco Lessicale.
Negli attacchi lessicali, si provano permutazioni di parole comuni o frasi derivanti da liste di password comuni. L’uso di permutazioni in questo contesto implica la generazione di varianti di password comuni che possono portare a brevi tempi di cracking.
La Permutazione
Nel calcolo combinatorio, una permutazione rappresenta la riorganizzazione di tutti i membri (quindi il numero di oggetti è uguale al numero di posti ) di un insieme in qualsiasi ordine o sequenza, nel quale conta l’ordine in cui i membri si dispongono.
Ad esempio, per l’insieme ABC, le possibili permutazioni sono: ABC, ACB, BAC, BCA, CAB e CBA.
Lo script Python allegato di seguito, partendo da una parola (o elenco di parole),
# ----------------------------------------------------------------------------- # - Script file name : perm.py # - Author : Nicola Montemurro # - DNS administrator: Nicola Montemurro - Tel. xxx, Mobile: xxx # - Create : 21.07.2025 # - Last Update : 24.07.2025 # - Description : # - Position : /usr/local/script/python # - note : NON modificare senza AUTORIZZAZIONE dell'AMMINISTRATORE # ---------------------------------------------------------------------------- #!/usr/bin/env python # -*- coding: utf-8 -*- import itertools import argparse import gc import sys import os def do_calculation(str_word, bucket_size, chars): #Genera tutte le permutation uniche della string (o della sua parte) e le restituisce progressivamente. #Rilascia le permutation periodicamente dal bucket per evitare troppa memoria accumulata. str_word = str_word[:chars] # Limita la string alla lunghezza specificata gc.enable() permutation = itertools.permutations(str_word) combination = set() # Utilizziamo un set per evitare duplicazioni counter = 0 bucket = [] for p in permutation: str_word = ''.join(p) if str_word not in combination: combination.add(str_word) bucket.append(str_word) counter += 1 # Rilascia il bucket di permutation ogni bucket_size permutation if counter >= bucket_size: for item in bucket: yield item # Restituisci una permutazione alla volta bucket.clear() # Pulisce il bucket counter = 0 # Reset del contatore #sleep(0.02) # Permette di gestire altre attività (DEBUG) # destroy objects del combination, bucket, counter # freeing memory gc.collect() # recreate objects combination = set() counter = 0 bucket = [] # Restituisci le restanti permutation se ci sono for item in bucket: yield item def main(): def avaluate_chars(user_input): # Controllo della lunghezza massima per la word if args.chars: if args.chars > len(user_input): nchars = args.chars nchars = args.chars else: nchars = len(user_input) # Se non viene specificata la lunghezza, utilizza tutta la word return nchars def avaluate_lenght(user_input): # Controllo della lunghezza massima per la word if args.lenght: if args.lenght > len(user_input): wlen = args.lenght wlen = args.lenght else: wlen = len(user_input) # Se non viene specificata la lunghezza, utilizza tutta la word return wlen # Impostazione di argparse per gestire gli argomenti parser = argparse.ArgumentParser(description="Genera tutte le permutazioni di una parola.") parser.add_argument("-w", "--word", type=str, help="Parola dalla quale generare le permutazioni.") parser.add_argument("-c", "--chars", type=int, help="Assume solo gli n caratteri della parola da permutare") parser.add_argument("-l", "--lenght", type=int, help="Limita il numero di caratteri (contando dal fondo) della parola permutata") parser.add_argument("-f", "--filename", type=str, help="Nome file contenente l'elenco di parole da cui generare le permutazioni.'") parser.add_argument("-b", "--bucket", type=int, default=1000000, help="Set di permutazioni da generare e rilasciare. (Default: 1000000)") args = parser.parse_args() data = None # Check if filename is provided if args.filename: # Ensure filename exists if not os.path.isfile(args.filename): print(f"Error: File '{args.filename}' not found or is not a valid file.") return # Exit gracefully try: # Try to open and read the file with open(args.filename, 'r') as file: for line in file: data = line.strip() max_chars=avaluate_chars(data) for word in do_calculation(data, args.bucket, max_chars): max_len=avaluate_lenght(data) print(word[-max_len:]) #print(word) except IOError as e: print(f"Error reading file '{args.filename}': {e}") return # Exit gracefully elif args.word: data = args.word.strip() max_chars=avaluate_chars(data) for word in do_calculation(data, args.bucket, max_chars): max_len=avaluate_lenght(data) print(word[-max_len:]) #print(word) # Check if input is from a pipeline elif not sys.stdin.isatty(): #print("Input is from a pipeline.") try: for line in sys.stdin: data = line.strip() max_chars=avaluate_chars(data) #print(f'{data}') for word in do_calculation(data, args.bucket, max_chars): max_len=avaluate_lenght(data) print(word[-max_len:]) #print(word) except Exception as e: print(f"Error reading from pipeline: {e}") return # Exit gracefully # Check if both input sources are empty # if data is None: #print("No input provided. Please specify a filename or pipe input.") #return # Exit gracefully if __name__ == '__main__': main()
In Conclusione
Le permutazioni sono un metodo utilizzato frequentemente durante la generazione delle password, di conseguenza l’utilizzo dello stesso per il password cracking risulta essere una buona soluzione.
Devifare il login per poter inviare un commento.