Dove conservi le tue corde di sale?


250

Ho sempre usato una stringa salata per voce corretta durante l'hashing delle password per l'archiviazione del database. Per le mie esigenze, l'archiviazione del salt nel DB accanto alla password con hash ha sempre funzionato bene.

Tuttavia, alcune persone consigliano di archiviare il sale separatamente dal database. Il loro argomento è che se il database è compromesso, un utente malintenzionato può comunque creare una tabella arcobaleno tenendo conto di una particolare stringa salt per tener conto di un account alla volta. Se questo account ha i privilegi di amministratore, potrebbe non essere nemmeno necessario decifrare altri.

Dal punto di vista della sicurezza, vale la pena conservare i sali in un posto diverso? Prendere in considerazione un'applicazione Web con il codice server e il DB sullo stesso computer. Se i sali sono memorizzati in un file flat su quella macchina, è probabile che se il database è compromesso, lo sarà anche il file di sali.

Ci sono soluzioni consigliate a questo?


9
Se c'è un posto dove è possibile archiviare il sale a cui l'attaccante non può arrivare, allora dovresti semplicemente archiviare anche le password lì. Ma perché non usare un sale diverso per ogni password?
jrockway,

8
Sta usando un sale diverso per ogni password, jrockway.
Ambra

9
Quanto sono grandi i tuoi sali? I tuoi sali dovrebbero essere abbastanza grandi (32 bit?) Che non c'è praticamente alcuna possibilità che una tabella arcobaleno sia stata pre-calcolata per questo.
M. Dudley,

@emddudley in questi giorni ho l'abitudine di usare un numero intero a 64 bit come il sale, ma non c'è motivo per non poterli prolungare.
friedo,

10
Autore di PWDTK qui sourceforge.net/projects/pwdtknet , onestamente non mi preoccuperei e conserverei il sale nello stesso DB della password. Dovresti sempre presumere che il sale sia noto a un utente malintenzionato, quindi dovresti concentrarti sull'uso di un sale LARGE CRYPTO-RANDOM e sull'allungamento dei tasti sufficiente (iterazioni in PBKDF2) in modo da rendere impossibile persino una tabella arcobaleno per un sale noto. Onestamente ciò che stai cercando di ottenere mettendo il sale altrove è "Security by Obscurity" e generalmente non serve a nulla quando guardi cose come un altro server potenzialmente andare giù.
thashiznets

Risposte:


259

Il punto delle tabelle arcobaleno è che sono state create in anticipo e distribuite in massa per risparmiare tempo di calcolo per gli altri - ci vuole tanto tempo per generare tabelle arcobaleno al volo come sarebbe solo rompere la combinazione password + sale direttamente (poiché effettivamente ciò che viene fatto quando si generano tabelle arcobaleno è pre-eseguire i calcoli per forzare bruscamente l'hash), quindi l'argomento secondo cui conoscendo il sale qualcuno potrebbe "generare una tabella arcobaleno" è falso.

Non ha senso archiviare i sali in un file separato fintanto che sono su una base per utente: il punto è semplicemente renderlo in modo che una tabella arcobaleno non possa violare tutte le password nel DB.


17
Concordato. Il modello di minaccia da cui stai proteggendo memorizzando il salt separatamente è un utente che può in qualche modo accedere al salt nel DB con mezzi nefasti, ma non l'hash (nel DB). E quella persona inizierà a calcolare in anticipo una tabella arcobaleno, supponendo che sarà in grado di trovare l'hash in seguito. Non impossibile, ma non degno dello sforzo ingegneristico per difendersi da questa via di attacco singola.
Tom Ritter,

Bel post, mi chiedevo la stessa cosa. Non ho mai pensato a un sale per utente, pensavo che un singolo sale avrebbe funzionato per tutti gli utenti. Che dire di un salt memorizzato come file XML che viene caricato dall'App Server? o forse in qualche modo hardcoded in un servlet?
jigzat,

9
@Jigzat - Salare è inutile se non hai un sale separato per ogni utente. Il punto saliente è rendere la rottura degli hash un'attività distinta per ogni password utente; se il sale è lo stesso per tutti loro, allora non è così.
Ambra

3
@TomRitter non è l'unico caso. si assume che tutte le password siano complicate. alcuni aggressori possono prendere il sale e l'hash e controllare solo le 10.000 password più comuni. in questo modo otterranno un numero decente di persone. se, tuttavia, non hanno accesso a Salt, è simile all'utente che ha una password più sicura e più lunga. ora, è probabile che il database salt sia sicuro mentre il database delle password viene rubato è in discussione, ma questo è un problema separato.
chacham15,

@Amber, credo che TomRitter abbia ragione. Memorizzare il sale separatamente significa la differenza tra forzare un attaccante a usare un attacco di forza bruta contro un attacco di dizionario più semplice. Se conosci il sale, puoi semplicemente aggiungerlo durante una serie dell'attacco del dizionario del mulino. Se riesci a difendere al 100% il tuo sale, puoi semplicemente usare lo stesso sale e forzare gli aggressori a forzare brutalmente tutto (anche per gli utenti che usano "password" come password). Ma puoi difendere il tuo sale ... probabilmente no. Quindi potrebbe anche ridurre i punti di errore memorizzandolo accanto all'hash e imporre regole di password più forti.
Ultratrunks,

35

Fornirò un approccio leggermente diverso su questo.

Conservo sempre il sale mescolato con l'hash con password salata.

Ad esempio, inserirò la prima metà del sale prima dell'hash salato della password e l'ultima metà del sale dopo l'hash salato della password. L'applicazione è a conoscenza di questo progetto, quindi può recuperare questi dati e ottenere l'hash salt e salted-password.

La mia logica per questo approccio:

Se i dati di password / hash sono compromessi e cadono nelle mani di un utente malintenzionato, quest'ultimo non saprà quale sia il problema derivante dall'osservazione dei dati. In questo modo un utente malintenzionato non può praticamente eseguire un attacco a forza bruta per ottenere una password che corrisponda all'hash, poiché non conosce l'hash per cominciare e non ha modo di sapere quali parti dei dati sono parti del sale, o parti dell'hash della password salata (a meno che non conosca la logica di autenticazione dell'applicazione ).

Se l'hash della password salata viene archiviato così com'è, è possibile eseguire un attacco di forza bruta per ottenere una password che, quando salata e hash, produce gli stessi dati dell'hash della password salata.

Tuttavia, ad esempio, anche se l'hash della password salata è stato archiviato così com'è, ma in attesa di un singolo byte casuale, fintanto che l'attaccante non è a conoscenza del fatto che questo primo byte deve essere scartato, ciò aumenterebbe anche la difficoltà di attacco. La tua applicazione saprebbe scartare il primo byte dei dati quando viene utilizzata per autenticare l'utente.

La conclusione a questo ..

1) Non archiviare mai i dati utilizzati dall'applicazione di autenticazione nella sua forma esatta.

2) Se possibile, mantenere segreta la logica di autenticazione per una maggiore sicurezza.

Fai un passo avanti ..

Se non riesci a mantenere segreta la logica di autenticazione dell'applicazione, molte persone sanno come vengono archiviati i tuoi dati nel database. E supponiamo che tu abbia deciso di memorizzare l'hash con password salata mescolato insieme con il sale, con parte del sale che precede l'hash con password salata e il resto del sale che lo aggiunge.

Quando generi il sale casuale, puoi anche decidere in modo casuale quale proporzione del tuo sale memorizzerai prima / dopo l'hash della password salata.

Ad esempio, si genera un sale casuale di 512 byte. Aggiungi il sale alla tua password e ottieni l'hash SHA-512 della tua password salata. Si genera anche un numero intero casuale 200. Quindi si memorizzano i primi 200 byte del sale, seguiti dall'hash della password salata, seguito dal resto del sale.

Quando si autentica l'immissione della password di un utente, l'applicazione passa sulla stringa e assume che il primo 1 byte dei dati sia il primo 1 byte del salt, seguito dall'hash salato. Questo passaggio fallirà. L'applicazione continuerà utilizzando i primi 2 byte dei dati come i primi 2 byte del sale e si ripeterà fino a quando non verrà trovato un risultato positivo dopo aver utilizzato i primi 200 byte come i primi 200 byte del sale. Se la password è errata, l'applicazione continuerà a provare tutte le permutazioni fino a quando non ne verrà trovata nessuna.

I pro di questo approccio:

Maggiore sicurezza - anche se la logica di autenticazione è nota, la logica esatta è sconosciuta al momento della compilazione. È praticamente impossibile eseguire un attacco a forza bruta, anche con la conoscenza della logica esatta. L'aumento delle lunghezze di sale aumenterà ulteriormente la sicurezza.

I contro di questo approccio:

Poiché la logica esatta viene dedotta in fase di esecuzione, questo approccio richiede molta CPU. Più lunga è la lunghezza del sale, più diventa intenso questo approccio alla CPU.

L'autenticazione di password errate comporterà il più alto costo della CPU. Questo può essere controproducente per richieste legittime, ma aumenta la sicurezza contro gli aggressori.

Questo approccio può essere implementato in vari modi e può essere reso ancora più sicuro utilizzando sali a larghezza variabile e / o hash con password salate.


9
Con il tuo approccio stai semplicemente aggiungendo un segreto al tuo processo di hashing (l'algoritmo che applica il sale). Questo segreto che puoi aggiungere molto più facilmente aggiungendo un peperone in più al sale, ho provato a farlo notare nel mio tutorial . Le moderne funzioni di hash come BCrypt applicheranno il sale da sole, usando il sale originale in ogni iterazione, quindi non avresti comunque alcun controllo su questo.
martinstoeckli,

@martinstoeckli Mentre hai ragione sul fatto che BCrypt applica il sale da solo, la memorizzazione di quel salt + hash dipende da te come sviluppatore. Quindi, potresti facilmente aggiungere un peperone al sale + hash e persisterlo nel database. Quindi, al successivo recupero, si legge il valore dal database, si spoglia il valore di pepe e si passa il valore rimanente a BCrypt.
PeterToTheThird

2
@PeterToTheThird - Questo annullerebbe il vantaggio del pepe. Il pepe aggiunge un segreto lato server e funziona solo finché rimane segreto (opposto al sale). Un tipico attacco è l'iniezione SQL, quando qualcuno accede al database ma non al codice, un peperone archiviato nel database sarà inutile. La maggior parte delle implementazioni di BCrypt aggiungerà automaticamente il sale al valore di hash risultante, quindi questo valore contiene già il sale, il fattore di costo, l'algoritmo e l'hash. Questa stringa può essere memorizzata in un singolo campo della lunghezza di 60 caratteri.
martinstoeckli,

Per aggiungere, quando si utilizza una funzione di "rafforzamento dei tasti" come BCrypt, non si ha il controllo sull'uso del sale. Tuttavia, se si desidera utilizzare un pepe, è sufficiente aggiungere il pepe al sale e utilizzarlo come "sale pepato" al posto dell'ingresso "sale" per la funzione di hashing. Il "pepe" è quindi un dato adatto che non è archiviato nel database, ma incorporato nel codice di autenticazione o archiviato in un'altra posizione sicura. Ho affrontato il problema da una prospettiva generica, usando SHA-512 come funzione di esempio, ma BCrypt ecc. Può anche essere usato in modo simile.
Ibraheem,

2
@martinstoeckli: sì, l'implementazione effettiva dipende dalla funzione hash utilizzata. Ovviamente è necessario prendere in considerazione i parametri e gli output della funzione hash quando si implementa la logica di autenticazione. In definitiva, un pepe è solo un'altra variabile introdotta nella tua funzione di hashing, che non viene memorizzata nella stessa posizione del sale e dell'hash.
Ibraheem,

23

Spesso vengono anteposti all'hash e memorizzati nello stesso campo.

Non è necessario memorizzarli separatamente: il punto è utilizzare un salt casuale per ogni password in modo che una singola tabella arcobaleno non possa essere utilizzata contro l'intero set di hash delle password. Con sali casuali, un attaccante deve forzare bruscamente ogni hash separatamente (o calcolare una tabella arcobaleno per tutti i possibili sali - molto più lavoro).

Se avessi una posizione di archiviazione più sicura, sarebbe logico archiviare lì gli hash.


4
Ma cosa succede se tutte le password con hash sono trapelate, incluso il relativo sale corrispondente? Non è altrettanto insicuro?
mghaoui,

10
@mghaoui Ma se volessi conoscere la "password" dovresti comunque costruire una Rainbow Table per ogni sale, a meno che alcuni dei sali non siano uguali.
Franklin,

4

Basato sullo sviluppo del libro Applicazioni Web ASP.NET MVC 4 di William Penberthy:

  1. Per ottenere l'accesso ai sali archiviati in un database separato è necessario che gli hacker hackerino due diversi database per ottenere l'accesso al salt e alla password salata. Memorizzarli nella stessa tabella della password, o anche in un'altra tabella dello stesso database, significherebbe che quando gli hacker ottengono l'accesso al database, avranno accesso sia all'hash salt che alla password. Poiché la sicurezza include il processo di rendere l'hacking nel sistema troppo costoso o dispendioso in termini di tempo per valerne la pena, raddoppiare la quantità di accesso che un hacker dovrebbe ottenere dovrebbe rendere il sistema più sicuro.
  2. La facilità d'uso è il motivo principale per mantenere i sali nello stesso database delle password con hash. Non dovresti assicurarti che due database siano sempre disponibili contemporaneamente e sempre sincronizzati. Il vantaggio di avere un salt è minimo se ogni utente ha un salt randomizzato perché sebbene possa rendere più facile la scoperta della password di un individuo, la quantità di forza necessaria per decifrare le password del sistema nel suo complesso sarà elevata. In questo livello di discussione, è proprio quello che ci si aspetta: proteggere le password. Se gli hacker hanno acquisito una copia del database, i dati dell'applicazione sono già compromessi. A questo punto, il problema è mitigare i rischi degli utenti a causa del potenziale delle password condivise.
  3. Il requisito di mantenere due database separati collegati è ampio. Concesso, aggiunge la percezione della sicurezza, ma l'unico vantaggio che offre è che protegge una password, un singolo elemento di dati. Se ogni campo nel database fosse crittografato individualmente e questo stesso sale fosse usato per quello, sarebbe più logico archiviarlo separatamente dai dati perché la sicurezza di base del sistema è migliorata.

Se l'applicazione è in grado di eseguire l'autenticazione su entrambi i database, non è sostanzialmente la stessa di un database, se l'attaccante ha compromesso il codice dell'applicazione?
John Ernest,

0

Lo scopo di un sale è di rendere inutili tutte le tavole arcobaleno e di richiederne una nuova serie. Ci vuole tanto tempo per indovinare una stringa quanto per creare un tavolo arcobaleno. Ad esempio l'hash SHA-256 di "password" è 5e88 4898 da28 0471 51d0 e56f 8dc6 2927 7360 3d0d 6aab bdd6 2a11 ef72 1d15 42d8. Dopo l'aggiunta di un salt, come "badpassword", la nuova stringa da sottoporre a hash è "passwordbadpassword" che, a causa dell'effetto valanga, modifica drasticamente l'output in 457b f8b5 37f1 802e f9c8 2e46 b8d3 f8b5 721b 7cbb d485 f0bb e523 bfbe 73e6 58d6.

Normalmente il salt è semplicemente memorizzato nello stesso database della password, anche perché se un database viene violato, è probabile che lo sia anche l'altro.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.