Se md5 è solo insicuro a causa della sua velocità, perché questa soluzione non lo rende ragionevolmente sicuro?

-1

Ho intenzione di prefigurare ciò dicendo che non ho assolutamente alcun indizio quando si tratta di crittografia, ma sto postando questa domanda perché sono molto interessato e non ho dubbi che ci siano alcune persone intelligenti qui che lo faranno essere in grado di spiegarmelo come se avessi 5 anni.

Quindi, per quanto ne so, md5 è considerato insicuro a causa della rapidità con cui le cose possono essere sottoposte a hash, il che significa che gli attacchi di forza bruta sono molto facili e gli attaccanti potrebbero anche confrontare una password md5 con hash su una tabella pre-generata.

Ecco perché quando (usando php) computo md5("password"); e mi dà 5f4dcc3b5aa765d61d8327deb882cf99 Posso collegare quel valore in un sito come questo e in 45ms sputa indietro 5f4dcc3b5aa765d61d8327deb882cf99 MD5 : password

Ma cosa succede se aggiungo alcuni dati di "aiuto" all'inizio e alla fine della mia password?

<?php
    $helper = "Qw3r7y1uioP[4]AsdfGh5jkl3'z7xcvb9nm,.?";
    echo md5($helper."password".$helper);
?>

Restituisce 9f1f60fc8d76caa77b11810a0d68e0c5 (che lo stesso sito non è in grado di decifrare, anche se non sono sicuro che le tabelle arcobaleno potrebbero, sembra improbabile anche se vero?) che potrei quindi memorizzare, insieme al "helper" da confrontare a futura password inviata per posta:

<?php
    $helper = "Qw3r7y1uioP[4]AsdfGh5jkl3'z7xcvb9nm,.?";
    $accepted = "9f1f60fc8d76caa77b11810a0d68e0c5";

    $pass = $_POST["password"];

    if (md5($helper.$pass.$helper)==$accepted) {
        echo "Password was correct.";
    } else {
        echo "Password was incorrect.";
    }
?>

Cosa c'è di sbagliato in questo approccio? Sono sicuro che c'è qualche ragione per cui non è una buona idea, semplicemente non ho abbastanza comprensione di come md5 e la crittografia in generale funziona per capire perché.

    
posta John Michael Dorian 08.06.2014 - 19:54
fonte

2 risposte

3

La stringa helper non aiuta.

Se è pubblico, è solo un prefisso costante che l'utente malintenzionato deve aggiungere a ogni password. Fondamentalmente hai creato una leggera modifica di MD5 con gli stessi problemi dell'MD5 reale. Questo non fa nulla per fermare gli attacchi di forza bruta e potrebbe anche introdurre sottili punti deboli.

Sì, un utente malintenzionato non sarebbe in grado di utilizzare una tabella di ricerca MD5 standard. Ma data la potenza di calcolo dell'hardware attuale, non c'è bisogno di tabelle di ricerca in primo luogo: anche una vecchia GPU di gamer come la HD 6990 può calcolare 10 miliardi di hash al secondo . E l'hardware specializzato come un ASIC ha prestazioni molto migliori. Non sono riuscito a trovare cifre concrete per MD5, ma al momento puoi ottenere 200 miliardi di hash SHA-256 al secondo con hardware per soli $ 500.

Se la stringa helper è segreta, l'intera sicurezza della password dipende da questo segreto. Non appena la stringa è nota, l'utente malintenzionato può tentare nuovamente miliardi di possibili password al secondo.

Sì, questo è leggermente migliore del semplice MD5, ma introduce un inutile punto singolo di errore. L'intera ragione per cui abbiamo le password di hash invece di crittografarle è perché non vogliamo alcuna scorciatoia per un utente malintenzionato. Anche se l'hacker sa tutto del tuo sistema, gli hash dovrebbero essere ancora sicuri come prima. Questo ovviamente non è il caso nel tuo schema.

Quindi, in entrambi i casi, questo non è un vero miglioramento.

Tuttavia, l'idea di aggiungere stringhe casuali alla password porta a un concetto valido: algoritmi di hash delle password specializzati come bcrypt hanno un parametro extra per un cosiddetto "salt". Un salt è una stringa casuale unica che viene generata per password e mescolata nella procedura di hashing. Questo costringe un utente malintenzionato a rompere ogni hash individualmente, poiché ogni hash è stato calcolato essenzialmente con una variazione unica dell'algoritmo principale.

Salare da solo non è abbastanza, però. Il requisito più importante per un algoritmo di hash delle password è che deve essere computazionalmente costoso. Calcolare un hash dovrebbe usare molte risorse. Invece di miliardi di hash al secondo su hardware di serie, vogliamo solo pochi hash al secondo. Questo fa poca differenza per gli utenti legittimi, ma è un problema enorme se stai provando un attacco a forza bruta.

    
risposta data 08.06.2014 - 21:40
fonte
0

C'è molto errore nel tuo approccio.

  1. PVD nell'origine . Se si verifica un problema con il codice sorgente o viene visualizzato un messaggio di errore, il codice sorgente potrebbe rivelare il valore di $accepted . Ciò consentirebbe a un utente malintenzionato di utilizzare l'hash scoperto per attaccarlo offline. Potrebbero usare un computer estremamente potente e lanciare miliardi di possibilità di password con 0 latenza.
  2. md5 . Sono stati trovati collisioni per MD5. Ciò significa che non ha le caratteristiche di una funzione hash crittografica.
  3. No Throttling . Hai ragione riguardo alla velocità. Potrei scrivere uno script che registra costantemente il tuo server e il tuo codice non fa nulla per rallentarli. Nessun timeout, ecc.
  4. Il tuo codice non protegge nulla . So che il tuo codice è solo un esempio, ma per i futuri lettori questo codice PHP NON vuoi copiare e incollare. Dopo il ramo if else, sia gli utenti autenticati che gli utenti non autenticati tornano allo stesso percorso di esecuzione. Sarà quasi certamente meglio fare questo

    <?php
    $helper = "Qw3r7y1uioP[4]AsdfGh5jkl3'z7xcvb9nm,.?";
    $accepted = "9f1f60fc8d76caa77b11810a0d68e0c5";
    
    $pass = $_POST["password"];
    
    if (md5($helper.$pass.$helper)==$accepted) {
        echo "Password was correct.";
    } else {
        echo "Password was incorrect.";
        exit(0);
    }
    ?>
    

Quello che vuoi fare è usare una funzione più strong che è anche più lenta. In PHP è molto facile usare la funzione crypt() , che implementa bcrypt (che è abbastanza buono ma ci sono altri KDF che funzionano come scrypt). Ecco un esempio che ho preso direttamente dai documenti php. Questo è anche un codice errato, ma illustra come utilizzare l'input dell'utente per verificare una password.

<?php
    $hashed_password = crypt('mypassword');

    /* You should pass the entire results of crypt() as the salt for comparing a
    password, to avoid problems when different hashing algorithms are used. (As
    it says above, standard DES-based password hashing uses a 2-character salt,
    but MD5-based hashing uses 12.) */
    if (crypt($user_input, $hashed_password) == $hashed_password) {
        echo "Password verified!";
    }
?>

È bene notare che funzioni come SHA, md5 e altri ben noti algoritmi di hashing sono state progettate per essere veloci. Le funzioni rapide sono ciò che gli aggressori amano vedere!

    
risposta data 08.06.2014 - 20:24
fonte

Leggi altre domande sui tag