TL; DR: puoi memorizzare il sale in testo normale senza alcuna forma di offuscamento o crittografia, ma non darlo semplicemente a chiunque lo desideri.
Il motivo per cui utilizziamo i sali è per fermare gli attacchi precalcolo, come tabelle arcobaleno. Questi attacchi comportano la creazione di un database di hash e dei relativi testi in chiaro, in modo che gli hash possano essere cercati e convertiti immediatamente in testo normale.
Ad esempio *:
86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 ae9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 b84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 c ... 948291f2d6da8e32b007d5270a0a5d094a455a02 ZZZZZX151bfc7ba4995bfa22c723ebe7921b6ddc6961bc ZZZZZY18f30f1ba4c62e2b460e693306b39a0de27d747c ZZZZZZ
la maggior parte delle tabelle includono anche un elenco di password comuni:
5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8 passworde38ad214943daad1d64c102faec29de4afe9da3d password1b7a875fc1ea228b9061041b7cec4bd3c52ab3ce3 letmein5cec175b165e3d5e62c9e13ce848ef6feac81bff qwerty123
* Sto usando SHA-1 qui come esempio, ma spiegherò perché questa è una cattiva idea in seguito.
Quindi, se l'hash della mia password è 9272d183efd235a6803f595e19616c348c275055
, sarebbe estremamente facile cercarlo in un database a e scoprire che il testo in chiaro è bacon4
. Quindi, invece di passare qualche ora a decifrare l'hash (ok, in questo caso sarebbero pochi minuti su una GPU decente, ma ne parleremo più avanti) ottieni il risultato istantaneamente .
Ovviamente questo è un male per la sicurezza! Quindi, usiamo un sale. Un salt è un token univoco casuale memorizzato con ciascuna password. Supponiamo che il sale sia 5aP3v * 4! 1bN<x4i&3
e l'hash sia 9537340ced96de413e8534b542f38089c65edff3
. Ora il tuo database di password è inutile, perché nessuno ha tabelle arcobaleno che includono quell'hash. È computazionalmente impossibile generare tabelle arcobaleno per ogni possibile sale.
Quindi ora abbiamo costretto i cattivi a ricominciare a rompere gli hash. In questo caso, sarebbe abbastanza facile da decifrare dato che ho usato una password sbagliata, ma è comunque meglio che lui riesca a cercarla in un decimo di secondo!
Ora, visto che l'obiettivo of the salt serve solo per impedire la creazione di database pre-generati, non ha bisogno di essere crittografato o nascosto nel database. Puoi memorizzarlo come testo normale. L'obiettivo è costringere l'attaccante a dover decifrare gli hash una volta ottenuto il database, invece di poterli cercare tutti in una tabella arcobaleno.
Tuttavia, c'è un avvertimento. Se l'aggressore può accedere silenziosamente a un salt prima di entrare nel tuo database, ad es. attraverso una sceneggiatura che offre il sale a chiunque lo richieda, può produrre una tavola arcobaleno per quel sale il più facilmente possibile se non ce ne fosse uno. Ciò significa che potrebbe prendere silenziosamente il sale del tuo account amministratore e produrre una bella grande tabella arcobaleno, quindi hackerare il tuo database e accedere immediatamente come amministratore. Questo non ti dà il tempo di individuare che si è verificata una violazione e non c'è tempo per agire per prevenire danni, ad es. cambiare la password dell'amministratore / bloccare gli account privilegiati. Questo non significa che dovresti oscurare i tuoi sali o tentare di crittografarli, significa solo che dovresti progettare il tuo sistema in modo tale che l'unico modo in cui possono arrivare ai sali è entrare nel database.
Un'altra idea da considerare è un pepe. Un pepe è un secondo sale che è costante tra le singole password, ma non memorizzato nel database. Potremmo implementarlo come H (salt + password + pepper)
o KDF (password + pepper, salt)
per una funzione di derivazione della chiave - ne parleremo dopo. Tale valore potrebbe essere memorizzato nel codice. Ciò significa che l'attaccante deve avere accesso sia al database che al codice sorgente (o ai binari della webapp nel caso di ASP .NET, CGI, ecc.) Per tentare di violare gli hash. Questa idea dovrebbe essere utilizzata solo per integrare altre misure di sicurezza. Un peperoncino è utile quando sei preoccupato per gli attacchi SQL injection, in cui l'autore dell'attacco ha accesso solo al database, ma questo modello sta (lentamente) diventando meno comune man mano che le persone passano alle query parametrizzate. stai utilizzando query con parametri, giusto? Alcuni sostengono che un peperone costituisca sicurezza attraverso l'oscurità, dal momento che stai solo oscurando il pepe, il che è in qualche modo vero, ma non è per dire che l'idea sia priva di merito.
Ora siamo a una situazione dove l'attaccante può forzare ogni singolo hash della password, ma non può più cercare tutti gli hash in una tabella arcobaleno e recuperare immediatamente le password in chiaro. Quindi, come possiamo prevenire gli attacchi di forza bruta adesso?
Le moderne schede grafiche includono GPU con centinaia di core. Ogni core è molto bravo in matematica, ma non molto bravo nel processo decisionale. Può eseguire miliardi di calcoli al secondo, ma è piuttosto terribile quando si eseguono operazioni che richiedono ramificazioni complesse. Gli algoritmi di hash crittografici rientrano nel primo tipo di calcolo. In quanto tali, framework come OpenCL e CUDA possono essere utilizzati per accelerare notevolmente il funzionamento degli algoritmi hash. Esegui oclHashcat con una scheda grafica decente e puoi calcolare un eccesso di 10.000.000.000 di hash MD5 al secondo. Anche SHA-1 non è molto più lento. Ci sono persone là fuori con piattaforme di cracking per GPU dedicate contenenti 6 o più schede grafiche di fascia alta, con una velocità di cracking di oltre 50 miliardi di hash al secondo per MD5. Mettiamolo nel contesto: un sistema del genere può forzare brutemente una password alfanumerica di 8 caratteri in meno di 4 minuti .
Chiaramente hash come MD5 e SHA-1 sono troppo veloci per questo tipo di situazione. Un approccio a ciò consiste nell'eseguire migliaia di iterazioni di un algoritmo di hash crittografico:
hash = H (H (H (H (H (H (H (H (H (H (H ( H (H (H (H (... H (password + salt) + salt) + salt) ...)
Questo rallenta il calcolo dell'hash, ma non è perfetto . Alcuni sostengono l'utilizzo degli hash della famiglia SHA-2, ma questo non fornisce molta sicurezza aggiuntiva. Un approccio più solido consiste nell'usare una funzione di derivazione chiave con un fattore di lavoro. Queste funzioni accettano una password, una sale e un fattore di lavoro. Il fattore di lavoro è un modo per adattare la velocità dell'algoritmo ai requisiti hardware e di sicurezza:
hash = KDF (password, salt, workFactor)
I due KDF più popolari sono PBKDF2 e bcrypt. PBKDF2 funziona eseguendo iterazioni di un HMAC con chiave (sebbene possa utilizzare cifrature a blocchi) e bcrypt calcola e combina un gran numero di blocchi di testo cifrato dal cifrario a blocchi Blowfish. Entrambi fanno più o meno lo stesso lavoro. Una variante più recente di bcrypt chiamata scrypt funziona secondo lo stesso principio, ma introduce un'operazione che richiede molta memoria che rende il cracking su GPU e aziende FPGA completamente impossibili, a causa della larghezza di banda della memoria restrizioni.
Aggiornamento: a partire da gennaio 2017, l'algoritmo di hashing all'avanguardia scelto è Argon2, che ha vinto la competizione per l'hashing delle password.
Si spera che questo ti dia una buona panoramica dei problemi che dobbiamo affrontare durante la memorizzazione delle password e risponda alla tua domanda sulla conservazione del sale. Consiglio vivamente di controllare i "link di interesse" in fondo alla risposta di Jacco per ulteriori letture, così come questi link: