Perché la gente pensa che questo sia un modo sbagliato di cancellare le password?

39

Bene, per favore dimmi, cosa c'è di sbagliato con questo codice:

$password = "hello";
$password = md5($password);
for($i=1;$i<20;$i++){
    $password = md5($password);
}

È esattamente lo stesso di questo:

md5(md5(md5(md5(md5(md5(md5(mD5(md5(md5(md5(md5(md5(md5(md5(md5(mD5(md5(md5(md5(‌​md5($password))))))))))))))))))));

e non penso che un utente malintenzionato con il mio DB sia in grado di decodificare qualsiasi password con lunghezza > 2.

L'utente malintenzionato dovrebbe decrittografare questo elenco di hash md5 per poter ottenere la password in chiaro:

69a329523ce1ec88bf63061863d9cb14
0dcd649d4ef5f787e39ddf48d8e625a5
5d6aaee903365197ede6f325eb3716c5
cbe8d0c48ab0ed8d23eacb1621f6c5c3
8fa852c5f5b1d0d6b1cb0fad32596c71
91a84cf929b73800d2ff81da28834c64
45b7d5e4d3fca6a4868d46a941076b72
e5b7d9d10fef132829731255ef644319
b3af6ff5f5c7ae757ca816a6cb62f092
150f3682b2e58d1d0e1f789f9ba06982
3f76626950bf31dbc815c667ca4b2b43
44f4c75517671e12946aab3c8c293f98
442256b098b2d88e93428b08b5155308
7fd8ebc5bdff94f24a10decaa1ab64e8
d04bbc863839b720d932a697f0bf443b
de737c934db23c2d1d1026863e7583a8
d745f6394700c4ab1e9ded0924ea35d2
ce9428b51d3a63431c57a435423877b6
7017f40bdb4f1be1f5fae7dd0fc7b907

e con bruteforce, dovrebbe provare le combinazioni 36 32 (* 19), che è abbastanza inafferrabile; o mi sbaglio? Non è vero?

    
posta genesis 24.07.2011 - 16:27
fonte

15 risposte

34

Altri hanno descritto i limiti di questo metodo di hashing; Vorrei segnalare un errore concettuale nella domanda:

I don't think that attacker with my DB would be able to decrypt any password with lenght > 2

Attacker would have to decrypt this list of md5 hashes to be able to gain plain-password:

[list of intermediate results]

L'errore qui sta pensando che la complessità dei risultati intermedi fornisce alcuna protezione contro un attacco di dizionario a forza bruta. Penso che il richiedente stia pensando che l'attacco debba funzionare a ritroso, a partire dall'hash memorizzato e la forza bruta a turno ogni risultato intermedio.

Questo non è affatto vero; gli attacchi del dizionario ragionevoli inizieranno con le possibili password e attaccheranno l'intero stack 20-hash in una sola volta. Ecco lo schizzo dell'algoritmo:

for each candidate password:
    hash 20 times
    compare with stored hash

Usando questo per controllare tutte le possibili password di 3 caratteri (assumendo ASCII stampabile) richiederebbero solo 20 * 95 ^ 3 = 17147500 hash, che è fondamentalmente banale. L'uso di SHA-512 invece di MD5, pur avendo valori intermedi molto più grandi, sarebbe più sicuro solo perché ogni hash impiega un po 'più di tempo a calcolare.

tl; dr una funzione di hash complessa non può salvarti se la password stessa non ha abbastanza entropia.

    
risposta data 27.07.2011 - 03:25
fonte
76

Le cose sbagliate sul tuo metodo sono:

  • Usi troppo poche iterazioni (20 è troppo basso, dovrebbe essere 20000 o più): l'elaborazione della password è ancora troppo veloce, un malintenzionato con un PC di base sarà comunque in grado di "provare" decine di milioni di password per secondo.
  • Non c'è sale: un utente malintenzionato può attaccare più password con un costo per password molto basso, ad es. con tabelle precalcolate di password con hash (in particolare tabelle arcobaleno ).
  • Sei in procinto di inventare la tua crittografia. Non c'è nulla di sbagliato nell'essere curiosi e nel cercare di capire le cose, ma poiché non esiste un test sicuro per sapere se un determinato algoritmo è sicuro o meno, inventare la propria crittografia è spesso una ricetta per il disastro. Non farlo.

Quello che dovresti fare è usare bcrypt ; esiste un'implementazione PHP nella struttura di hashing della password PHP portatile .

    
risposta data 24.07.2011 - 17:00
fonte
17

20x MD5 è un algoritmo di hash veloce, il che significa che può generare password ad un ritmo sorprendente.

Si prega di smettere di usare algoritmi di hashing veloci per memorizzare le password. Anche con i sali individuali; se qualcuno ha accesso diretto (leggi: offline) al tuo database, può essere calcolato molto facilmente.

Questo articolo spiega perché molto meglio di quanto posso:

link

L'articolo menziona pesantemente BCrypt (con un link a una libreria PHP), ma tieni presente che ci sono altri algoritmi di hashing lenti che potrebbero essere adatti a te.

    
risposta data 24.07.2011 - 17:43
fonte
11

Il problema è che questo è un "algoritmo" piuttosto ovvio e abbastanza veloce da avviare.
È molto probabile che sia disponibile una tabella arcobaleno precalcolato per questo "algoritmo", e anche se non lo è, md5 è abbastanza veloce da essere in grado di precomputerne uno in un lasso di tempo realistico.

Dovresti sempre utilizzare un singolo salt per ogni password per evitare questo tipo di attacco.

    
risposta data 24.07.2011 - 16:33
fonte
10

A parte ciò che è già stato sottolineato nelle altre risposte finora, mi sembra che tu abbia un malinteso fondamentale seduto lì nella tua domanda. Lo spazio di output di una funzione hash a 128 bit come MD5 non è 36 ^ 32 (circa 6.3e49), ma 2 ^ 128 (circa 3.4e38). Sono 11 ordini di grandezza!

La crittografia è difficile. Se non sai esattamente cosa stai facendo (e in molti casi anche se lo fai), sei molto, molto meglio non provare a progettare qualcosa da te, ma piuttosto usare un ready-made, soluzione provata e vera. Per un esempio di vita reale di come possono andare cose terribilmente sbagliate quando non sai esattamente cosa stai facendo, cerca la debacle della chiave Debian OpenSSL . La versione preliminare di Netscape PRNG è un altro esempio. Sono sicuro che ce ne sono molti altri, più o meno ampiamente pubblicizzati.

    
risposta data 25.07.2011 - 14:30
fonte
9

Ci sono quattro problemi con l'iterazione di md5 ripetutamente, non importa quante volte lo fai.

Computing Power over Time

Il primo grosso problema qui è che, come scritto, non si ridimensiona nel tempo per rimanere al sicuro man mano che i computer diventano più veloci. Ciò che è sicuro oggi sarà rotto nei momenti nei computer di domani.

Algoritmi sicuri moderni come bcrypt e scrypt sono integrati nel tuning in modo che l'algoritmo possa essere regolato automaticamente per essere più lento man mano che i computer che attaccano diventano più veloci. Poiché bcrypt è anche gratuito ed è ancora una semplice funzione chiamata per te, non c'è alcun buon motivo per non usarlo.

Ora hai start di una struttura di scalabilità integrata nel tuo codice. Sarebbe facile refactoring per eseguire l'hash MD5 un numero arbitrario di volte, in modo da poterlo regolare più lentamente nel tempo. Ma non è abbastanza buono.

Progettato per l'errore

Il secondo problema è che md5 è una scelta fondamentalmente povera per un hash crittografico perché è stato specificamente progettato per essere veloce . Lo scopo di MD5 è quello di verificare o confrontare rapidamente file di grandi dimensioni. Per fare ciò, l'hash deve essere in grado di essere calcolato rapidamente ed efficientemente. Ciò significa che gli obiettivi di implementazione e progettazione dell'algoritmo sono completamente in disaccordo con l'archiviazione delle password. Le probabilità che a un certo punto capiremo un modo per calcolare un hash MD5 che sia più veloce di quello che possiamo fare attualmente è di ordini di grandezza superiore a quello che saremo in grado di fare lo stesso per sha1 o bcrypt.

Degenerazione

Il terzo problema è che gli algoritmi di hashing in generale tendono a degenerare man mano che vengono iterati. Per capire questo, prendi il testo originale fornito dall'utente. La dimensione concettuale di questo testo è illimitata . Qui c'è un infinito numero di valori possibili. Dopo aver cancellato il testo una volta con md5, siamo al 2 128 numero di valori possibili ... ancora molto grandi, ma non più illimitati. Ma andiamo di nuovo in ciclo. md5 è buono, ma non è perfetto . Quei potenziali 340 undecillion avranno delle collisioni e produrranno un numero di risultati vicino, ma ancora un po 'meno di, 2 128 . Continuando a scorrere, troverai più collisioni, finché alla fine non troverai un numero che, pur essendo ancora grande, è significativamente inferiore allo spazio concettuale con cui hai pensato di lavorare.

Cicli

Infine, il quarto problema è che alcuni dei tuoi potenziali input iniziali risulteranno in cicli : numero di valore 12345 hash su 98743, hash su 67321, hash su 12345 e così via. In altre parole, alcuni input passeranno in rassegna lo stesso piccolo insieme di valori hash, e iterandoli ulteriormente non aiuterà . Infatti, più volte esegui l'hash, più probabilmente un dato input originale finirà in un ciclo.

Questo torna al design di md5. Un hash crittografico potrebbe essere progettato per minimizzare (non eliminare completamente, ma almeno minimizzare) i fenomeni di degenerazione e di ciclo, ma non era affatto un problema per MD5.

Conclusione

Qualcuno di questi motivi è sufficiente per non usare md5. Ci sono altre opzioni perfettamente valide disponibili e generalmente usano la stessa interfaccia, quindi sceglierne una diversa non è difficile. In alcune piattaforme, è facile come modificare un valore enum che passi ad alcune funzioni di "createhash". Metti insieme tutti e tre i motivi, e continuare a usare md5 è assolutamente folle.

    
risposta data 24.07.2011 - 20:51
fonte
7

Hai una semplice funzione di hashing unidirezionale per le password, sembra sicuro vero? Dovresti attraversare un sacco di ipotesi per forzare un tale sistema. Tuttavia, si consideri uno scenario negativo (nemmeno nel peggiore dei casi). Utilizzi questo livello di sicurezza con un sito di altissima importanza o persino un sito con molti utenti.

Poi, un giorno c'è un piccolo problema di sicurezza o il tuo sito ha una vulnerabilità precedentemente sconosciuta che viene sfruttata e tutti i dati del tuo account utente, comprese le password con hash, sono ora nelle mani di "cattivi". I cattivi vanno al loro PC a basso costo con una GPU decente e modificano un programma precedentemente esistente per generare hash in modo che faccia 19 livelli di hashing MD5. Quindi gli forniscono un dizionario ben affinato di password comuni e probabili e stringhe alfanumeriche casuali di lunghezza crescente. Nel tempo la GPU passa attraverso la generazione di hash creando una tabella di ricerca. In qualsiasi momento i malintenzionati possono controllare la loro tabella di ricerca hash generata nell'elenco delle password con hash e, poiché non si è utilizzato un sale per password, trovare facilmente le corrispondenze. Nel tempo, mentre la GPU continua a funzionare, vengono rivelate sempre più password, fino a quando rimangono solo le password con la massima resistenza.

    
risposta data 25.07.2011 - 04:56
fonte
6

MD5 non è il miglior hash da usare al giorno d'oggi per la sicurezza al giorno d'oggi; gli hash possono essere calcolati troppo velocemente (sebbene il difetto più grande con md5 sia la facilità nel generare collisioni). I suoi soli 128 bit (16 ^ 32 = 2 ^ 128 ~ 10 ^ 38); prova sha-256 (2 ^ 256 ~ 10 ^ 77, le sue 2 ^ 128 volte più chiavi) o sha-512. Il rinforzo chiave è una buona pratica (ad esempio, ci vuole 20 volte di più per generare una tabella arcobaleno); ma ancora 20 volte più a lungo non è così lungo (ad esempio, usa 20 macchine e richiede altrettanto tempo), ma è fatto meglio con un sale casuale. Sarebbe molto meglio rafforzare la chiave dire 100000 volte.

$password = "hello";
$salt = random_str(); // generate some relatively short random str
$password = sha256($password);
for($i=1;$i<100000;$i++){
    $password = sha256($salt + $password);
}
$sep = "|";
$password_scheme = "SHA256x100k";
$password = $salt + $sep + $password_scheme + $sep + $password;

Uso di un linguaggio pseudo-codice in cui + concatena stringhe e random_str () è una funzione che genera una stringa casuale breve. Lo scopo del sale casuale è che se un utente malintenzionato vede il tuo codice sorgente, vede gli hash delle password, devono generare una tabella arcobaleno separata per ogni sale diverso (o uno per ogni password). Così ora, invece di dover generare una sola tabella arcobaleno per ottenere tutte le password degli utenti, devono generare una tabella arcobaleno per ottenere solo una password. Inoltre, è una buona idea documentare lo schema delle password nell'hash, quindi è possibile aggiornarlo come necessario, ad es., Migrare da SHA256x100k a SHA256x1k se è necessario utilizzare meno risorse della CPU o decidere di passare a un hash differente in seguito.

È scontato che non sia la migliore idea di inventare il tuo metodo crittografico personalizzato se non sei un esperto di crittografia. Sicuramente lasci l'opportunità di subdoli problemi di sicurezza come gli attacchi timing anche con algoritmi apparentemente sicuri. bcrypt è probabilmente la soluzione migliore.

Nota: MD5 è particolarmente vulnerabile agli attacchi di collisione, ma in realtà non devi preoccuparti delle collisioni negli attacchi preimage (che è il metodo di attacco contro gli hash delle password). Un utente malintenzionato ha ottenuto un elenco di hash delle password (h) in qualche modo e ha imparato la routine hash (md5 x 20 o salato sha256 x 100k) e sta cercando di ottenere qualsiasi messaggio m, tale che hash_routine (m) = h, per consentire loro nel tuo sistema.

La vulnerabilità di collisione che ti preoccupa è che se hai un hash (m1) = hash (m2) quando m1! = m2; quindi se scarichi qualcosa in cui le persone hanno controllato che il file m1 sia sicuro e vuoi assicurarti che tu abbia effettivamente scaricato m1, confronta hash (m1) con l'hash pubblico md5. Se c'è una versione malevola m2 con lo stesso hash md5, non puoi essere sicuro che m1 sia sicuro controllando la sua somma md5.

    
risposta data 25.07.2011 - 20:03
fonte
5

Le tabelle arcobaleno funzionano perché più sistemi utilizzano schemi simili per la gestione dei dati. Mentre è ben considerato che l'aggiunta di un sale dovrebbe essere una caratteristica universale dell'hash delle password, l'aggiunta di un numero di round aiuta anche a sconfiggere le tabelle arcobaleno. Per arguzia: una tabella arcobaleno per qualsiasi sottoinsieme di caratteri in MD5 non può risultare in una corrispondenza per qualsiasi password nel tuo sistema eccetto per collisione accidentale. La funzione di riduzione della tabella arcobaleno converte ogni hash generato in una stringa che corrisponde alla lettera, al numero e al modello di simbolo per cui è progettata la tabella. Nel momento in cui un hash viene generato dal tuo metodo che include un simbolo al di fuori di tale intervallo (una certezza virtuale come input per la tua funzione di hash è l'out di un hash), impedirà il funzionamento della tabella.

Il fatto che il tuo sistema sia semplice o persino pubblicamente conosciuto non ha importanza, tanto che sconfiggere una tabella arcobaleno richiede solo che gli hash non possano essere stati creati in gran numero dal metodo utilizzato per generare quella tabella.

Wikipedia ha preso in considerazione il problema dell'hash nel tempo in quanto il suo database utenti è ben noto, molto vecchio e ha utilizzato vari metodi di hashing che ora sono insicuri. La soluzione discussa è stata la chiave di volta dei vari metodi. Per calcolare una password, viene cercata la versione del metodo hash e la password viene calcolata in base a tale. Al login con un hash della vecchia versione, verrebbe aggiornato alla versione più recente.

Thomas ha detto che dovresti usare più turni per il tuo hashing. Ciò di cui non si è parlato è il modo in cui si determina il numero di round da utilizzare. La risposta a questo è sfocata, ma sostanzialmente si riduce a "quante iterazioni posso eseguire per il carico di accesso sul mio sistema?" Se hai 10.000 utenti che accedono ogni minuto, potresti essere disposto a dedicare un carico di CPU del 25% a questo. Per questo, scegli un numero di iterazioni che ti permetta di fare circa 700 calcoli al secondo.

    
risposta data 24.07.2011 - 17:56
fonte
4

No, ti sbagli. Il problema con gli hash md5 è che c'è una possibilità relativamente grande sulle collisioni: ci sono molte stringhe che producono lo stesso hash. E poiché ci sono solo 36 ^ 32 possibilità, che possono essere provate in circa 35 ore, credo (e otterrà un risultato molto prima perché c'è una grande possibilità di collisioni), non è più considerato un buon hash. Per non parlare del fatto che probabilmente esiste una tabella arcobaleno per 20 hash md5. Inoltre, c'è gente che dice che md5 è effettivamente reversibile, ma non ne sono sicuro.

Ci sono due modi per rendere le tue password più difficili da hackerare:

  1. Utilizzare un sale statico. Ciò rende inefficaci le tabelle arcobaleno, perché l'hacker non può più usare solo parole inglesi, dal momento che il tuo sale (che l'hacker, si spera non lo sappia) sta componendo gran parte della stringa. Prova i sali lunghi composti da molti caratteri speciali;
  2. Utilizzare un algoritmo di hashing migliore e più lungo come whirlpool o sha512. Ciò ovviamente aumenta notevolmente la quantità di possibilità;
  3. Hash your string multiple (x) times. Questa è una delle cose che hai fatto bene: se l'hacker conosce il tuo sale e la quantità di volte che hai (in pratica ha accesso al tuo codice sorgente e al database), questo fa sì che gli occorrano x volte più a lungo per ottenere risultati ;
  4. Crea un sale dipendente dalla stringa. Questo è un salt generato in modo casuale per ogni stringa salvata nel database e memorizzata insieme ad essa. Questo assicura che l'hacker debba ripetere ogni possibilità dell'hash per ogni password, invece di essere in grado di farlo una volta per ogni password memorizzata. Se hai 500 password memorizzate nel database, in questo modo l'hacker impiega 500 volte di più a hackerare tutte le password.

Spero che questo sia stato di aiuto. :)

    
risposta data 24.07.2011 - 16:47
fonte
2

Generalmente, non c'è nulla di sbagliato nell'applicare un valore più volte per renderlo più robusto contro gli attacchi di forza bruta. In effetti, questa è una tecnica già applicata nota come stretching chiave .

Le uniche obiezioni al tuo esempio sono che dovresti usare un algoritmo di hashing crittograficamente strong e uno schema di hashing che include un sale per più entropia e resistenza a attacchi da tavolo arcobaleno . Nel migliore dei casi uno schema di archiviazione delle password già provato come crypt è stato progettato specificamente per le password.

    
risposta data 24.07.2011 - 16:53
fonte
2

I don't think that attacker ... would be able to

Stai presupponendo che tu sappia come funzionano gli autori di attacchi.

Stai partendo dal presupposto che tu sappia tutti i trucchi che gli attaccanti usano e che hai difeso con successo contro ognuno di loro.

Si presume che non ci sia nulla nella ricerca pubblicata, la conoscenza che è disponibile per chiunque abbia voglia di imparare, che potrebbe aiutare anche un aggressore moderatamente esperto a violare la sicurezza.

Si presume che l'attaccante non sia disposto nemmeno a eseguire un attacco di forza bruta con calcolo rubato. (Avete considerato lo scenario in cui un utente malintenzionato è paziente e fa un lavoro in background sul server di qualcun altro, un server in cui l'hacker si è incrinato e non sta pagando, allo scopo di scomporre il file della password per un periodo di un mese ?)

Questo di solito è un presupposto pessimo .

    
risposta data 28.09.2011 - 03:38
fonte
1

Link correlati:

risposta data 31.10.2011 - 16:58
fonte
0

Capisco che questa domanda sia già qui da un po 'di tempo e ha delle risposte eccellenti. Comunque penso che ci sia un problema che non è stato affrontato. Utilizzare un algoritmo strong (da una libreria) è la strada da percorrere, dal momento che tali metodi sono stati testati. Ma ecco quello che vedo:

I don't think that attacker with my DB would be able to decrypt any password with lenght > 2

Il problema non è la creazione dell'algoritmo più impossibile da decodificare. Il problema è proteggere il tuo database. Ad esempio se l'attaccante ha una sospensione del tuo database, non credo che si preoccuperà molto delle password in esso contenute.

    
risposta data 28.09.2011 - 01:36
fonte
-5

Problemi con il tuo metodo è che con ogni chiamata su md5 stai ingrandendo lo spazio di collisione delle tue password ( nessuna dimostrazione matematica, solo comprensione ingenua ). Per quanto figo possa sembrare, non cercare di rendere la tua sicurezza più complicata di quanto ne abbia bisogno. L'hashing algeo è tanto solido quanto l'uso di più pseudo-casuali per provare a generare un casuale sicuro. Potresti ottenere una sicurezza semplice che sia abbastanza sicura se applichi la pratica del buon senso.

Ad ogni modo, il solito consiglio si presenta, usa il sale con un algo che ha uno spazio di collisione abbastanza grande. Se vuoi più sicurezza, dovresti considerarli ad altri livelli, come la sicurezza del server, la sicurezza del personale di gestione.

Ad ogni modo se vuoi applicare altri consigli sull'uso di bcrypt ( che è tanto brutto quanto necessario per ottenere la chiave per decifrare l'intero elenco delle password [ O (n) una volta ottenuta la password], evitando di guardare a una tabella arcobaleno contro ogni voce [ O (n * m) ]), ti consiglio almeno di usare una chiave pubblica cifrata in quanto la chiave per decrittografare i dati non sarebbe necessaria nella verifica dell'input (usa la chiave per crittografare nello stesso modo in cui hai cancellato i tuoi dati).

    
risposta data 25.07.2011 - 04:42
fonte

Leggi altre domande sui tag