it-swarm-eu.dev

Hashing password: aggiungi sale + pepe o sale è sufficiente?

Nota: Sono consapevole che il metodo corretto per l'hash di archiviazione sicura delle password è scrypt o bcrypt. Questa domanda non è per l'implementazione nel software reale, è per mia comprensione.

correlati


Background
Per quanto ne so, il metodo raccomandato/approvato per l'archiviazione dei verificatori di password è di memorizzare:

$verifier = $salt + hash( $salt + $password )

Dove:

  • hash() è un algoritmo di hash crittografico
  • $salt È un valore entropico casuale, uniformemente distribuito
  • $password È la password inserita dall'utente

Alcune persone consigliano di aggiungere una chiave segreta nel mix (a volte chiamato pepe ). Dove il pepe è una costante segreta, ad alta entropia, specifica del sistema.

La logica sembra essere che anche se l'attaccante ottiene i verificatori di password, ci sono buone probabilità che non conosca il valore di pepe. Quindi montare un attacco riuscito diventa più difficile.

Quindi, la mia domanda è:
L'aggiunta di un valore di pepe oltre a un valore salato quando le password di hashing aumenta la sicurezza complessiva?

O la maggiore sicurezza percepita si basa su presupposti falsi?

Aggiornamento rapido
Conosco lo scopo di $salt (Ho scritto un bel risposta lunga su StackOverflow al riguardo) il tasto aggiuntivo $pepper È no migliorare su ciò che fa il sale.
La domanda è: $pepper Aggiunge sicurezza altro di quello che fa il sale?

234
Jacco

In alcune circostanze, i peperoni possono essere utili.

Ad esempio, supponiamo che stai creando un'applicazione Web. È costituita da codice webapp (in esecuzione in alcuni framework webapp, ASP.NET MVC, Pyramid su Python, non importa) e un database SQL per l'archiviazione. La webapp e il DB SQL eseguono su diversi server fisici.

L'attacco più comune al database è un attacco SQL Injection riuscito. Questo tipo di attacco non ottiene necessariamente l'accesso al codice della tua webapp, poiché la webapp viene eseguita su un altro server e ID utente.

Devi archiviare le password in modo sicuro nel database e trovare qualcosa sotto forma di:

$hashed_password = hash( $salt . $password )

dove $salt è memorizzato in chiaro nel database, insieme alla rappresentazione $hashed_password e scelto casualmente per ogni password nuova o modificata.

L'aspetto più importante di ogni schema di hashing della password è che hash è un lento funzione hash crittograficamente sicura, vedere https://security.stackexchange.com/a/31846/10727 per ulteriori informazioni di base.

La domanda è quindi dato che è quasi zero lo sforzo di aggiungere un valore costante al codice dell'applicazione e che il codice dell'applicazione in genere non essere compromesso durante un attacco SQL Injection, quanto segue è sostanzialmente migliore di quanto sopra?

$hashed_password = hash( $pepper . $salt . $password )

dove $salt è archiviato in testo normale nel database e $pepper è una costante memorizzata in testo normale nel codice dell'applicazione (o configurazione se il codice viene utilizzato su più server o l'origine è pubblica).

Aggiungere questo $pepper È facile: stai semplicemente creando una costante nel tuo codice, inserendo un grande valore casuale crittograficamente sicuro (ad esempio 32 byte da/dev/urandom hex o base64 codificato) e usando quello costante nella funzione di hashing della password. Se hai utenti esistenti hai bisogno di una strategia di migrazione, ad esempio ridisegna la password al prossimo accesso e memorizza un numero di versione della strategia di hashing della password insieme all'hash.

Risposta:

L'uso di $pepper aggiunge alla forza dell'hash della password se compromissione del database non implica compromissione dell'applicazione. Senza la conoscenza del pepe le password rimangono completamente sicure. A causa del salt specifico della password non è nemmeno possibile scoprire se due password nel database sono uguali o meno.

Il motivo è che hash($pepper . $salt . $password) crea in modo efficace una funzione pseudo casuale con $pepper Come chiave e $salt.$password Come input (per i sani candidati hash come PBKDF2 con SHA * , bcrypt o scrypt). Due delle garanzie di una funzione pseudo casuale sono che non è possibile dedurre l'input dall'output in una chiave segreta e né l'output dall'input senza la conoscenza della chiave. Sembra molto simile alla proprietà unidirezionale delle funzioni hash, ma la differenza sta nel fatto che con valori di entropia bassi come le password è possibile enumerare efficacemente tutti i valori possibili e calcolare le immagini con la funzione hash pubblica e trovare quindi il valore di cui l'immagine corrisponde alla pre-immagine. Con una funzione pseudo casuale non puoi farlo senza il tasto (cioè senza il pepe) in quanto non puoi nemmeno calcolare l'immagine di un singolo valore senza il tasto.

L'importante ruolo di $salt In questa impostazione entra in gioco se si ha accesso al database per un periodo di tempo prolungato e si può ancora lavorare normalmente con l'applicazione dall'esterno. Senza $salt Potresti impostare la password di un account che controlli su un valore noto $passwordKnown E confrontare l'hash con la password di una password sconosciuta $passwordSecret. Come hash($pepper . $passwordKnown)==hash($pepper . $passwordSecret) if e solo se $passwordKnown==$passwordSecret Puoi confrontare una password sconosciuta con qualsiasi valore scelto (come tecnicamente presumo resistenza alla collisione della funzione hash). Ma con il sale ottieni hash($pepper . $salt1 . $passwordKnown)==hash($pepper . $salt2 . $passwordSecret) se e solo se $salt1 . $passwordKnown == $salt2 . $passwordSecret E come $salt1 E $salt2 Sono stati scelti casualmente per $passwordKnown E rispettivamente $passwordSecret I sali non saranno mai gli stessi (assumendo valori casuali abbastanza grandi come 256 bit) e quindi non puoi più confrontare le password l'una con l'altra.

195
Jesper M

(Nota: usare un salt è solo metà del lavoro; devi anche rallentare la funzione di hash - in modo che attaccare una singola password a bassa entropia sia ancora difficile. La lentezza di solito si ottiene attraverso più iterazioni, o hashing la concatenazione di 10000 copie di Salt e password.)

Quello che fa il tuo "pepe" è che trasforma l'hash in un MAC . Creare un buon MAC sicuro da una funzione hash non è facile, quindi è meglio usare HMAC invece di un costrutto fatto in casa (il modo teorico di mettere è che una funzione hash resistente alle collisioni non è necessariamente indistinguibile da un Oracle casuale).

Con un MAC, l'utente può ottenere un po 'di sicurezza nel seguente senso: probabilmente, l'accesso in lettura al database da parte dell'attaccante potrebbe smettere di essere un vero problema. Il tasto MAC (il "pepe") può concentrare la necessità di riservatezza. Tuttavia, ciò si basa sul fatto che il MAC è anche una funzione a senso unico, che è una proprietà che otterrai da molte costruzioni MAC (incluso HMAC) ma che non è realmente garantita dal punto di vista crittografico (ci sono sottigliezze).

Il "pepe" implica che hai una chiave da gestire, incluso l'archiviazione sicura in un modo che resiste al riavvio. Una chiave è piccola e si adatta alla RAM, ma, a causa dei requisiti di archiviazione, non è chiaro se effettivamente migliora la sicurezza. Un utente malintenzionato in grado di leggere l'intero database in genere può anche leggere l'intero disco rigido, incluso qualsiasi file "protetto". Le dimensioni ridotte della chiave possono consentire alcune configurazioni avanzate, ad es. la chiave viene memorizzata su smart card che vengono utilizzate all'avvio ma non vengono successivamente collegate. Per riassumere, se valga la pena approfondire lo sforzo dipende dal contesto: su base generale, lo sconsiglio, per evitare la complessità aggiunta.

90
Thomas Pornin

Vorrei sottolineare cosa può davvero fare un pepe.

Quando aiuta un pepe?

Come hanno già sottolineato gli altri, l'aggiunta di un pepe è solo un vantaggio, a condizione che l'attaccante abbia accesso ai valori di hash nel database, ma non abbia alcun controllo sul server e quindi non conosco il pepe. Questo è tipico dell'iniezione SQL, probabilmente uno degli attacchi più utilizzati, perché è così facile da eseguire.

Cosa migliora un peperone?

$hashValue = bcrypt('12345', $cost, $salt);

Questa password è possibile ottenere facilmente con un attacco del dizionario, anche se è stata utilizzata correttamente una funzione di derivazione dei tasti lenta. Inserisci le password più utilizzate in un dizionario e forza bruta con queste password deboli. È molto probabile che troviamo la password (anche) in molti casi.

$hashValue = bcrypt('12345anm8e3M-83*2cQ1mlZaU', $cost, $salt);

Con il pepe, la password debole cresce in lunghezza, ora contiene caratteri speciali e, cosa più importante, non la troverai in nessun dizionario. Quindi, fintanto che il pepe rimane segreto, fa prevenire gli attacchi del dizionario, in questo caso può proteggere le password deboli.

Modificare:

C'è un modo migliore per aggiungere una chiave lato server, piuttosto che usarla come pepe. Con un peperone un utente malintenzionato deve ottenere ulteriori privilegi sul server per ottenere la chiave. Lo stesso vantaggio si ottiene calcolando prima l'hash e successivamente crittografando l'hash con la chiave lato server (crittografia bidirezionale). Questo ci dà la possibilità di scambiare la chiave ogni volta che è necessario.

$hash = bcrypt($passwort, $salt);
$encryptedHash = encrypt($hash, $serverSideKey);
26
martinstoeckli

L'articolo sull'invenzione della salatura e delle iterazioni, per le password Unix ( Password Security: A Case History, Morris & Thompson, 1978 ), descriveva anche l'equivalente di un pepe:

I primi otto caratteri della password dell'utente sono usati come chiave per il DES; quindi l'algoritmo viene utilizzato per crittografare una costante. Sebbene al momento questa costante sia zero, è facilmente accessibile e può essere resa dipendente dall'installazione.

Non ne ho mai sentito parlare. Qualcun altro?

9
nealmcb

Solo un BTW, le nuove NIST Digital Idendity Guidelines (Draft) raccomandano caldamente di usare anche Pepper:

https://pages.nist.gov/800-63-3/sp800-63b.html#sec5

5.1.1.2 Verifica dei segreti memorizzati:

... Una funzione hash con chiave (ad es. HMAC [FIPS198-1]), con la chiave memorizzata separatamente dagli autenticatori con hash (ad es. In un modulo di sicurezza hardware) DOVREBBE essere utilizzata per resistere ulteriormente agli attacchi del dizionario contro gli autenticatori con hash memorizzati.

7
eckes

Considera questo scenario:

Sto per entrare in un sito Web X usando un'iniezione SQL per recuperare un elenco di utenti, con i loro hash password e salt. Supponiamo che anche il sito Web X stia usando un peperone globale.

Tutto quello che dovrei fare sarebbe registrare un utente sul sito Web X con un nome utente e una password a me noti prima dell'iniezione SQL. Vorrei quindi sapere, per un particolare record nel database, l'hash della password, la password del testo normale, il salt (memorizzato come testo normale) e sarebbe computazionalmente banale per me rompere il pepe globale sulla base di questo record .

Quindi davvero, un peperone sarebbe un modo per rallentare un attaccante per un tempo insignificante. Non avrebbero dovuto forzare la password + sale + pepe, come previsto, solo il pepe.

Quanto sopra è una forma di attacco di testo in chiaro scelto. Fintanto che gli aggressori conoscono l'algoritmo (hash ()), l'output ($ hashed_password) e tutti gli input tranne uno ("costanti" $ salt & $ password e "variabile" $ pepper), possono "risolvere per x "come un'equazione di algebra lineare (h = s + p + x == hsp = x), ma ovviamente per forza bruta. Rendere il pepe più lungo di 56 byte (448 bit), il limite di bcrypt, aumenta il costo del tempo ed è buono come bcrypt ma potrebbe non essere buono come scrypt. Quindi, finché il pepe è sufficientemente lungo, è un miglioramento.

4
Alex R

Non ho molta familiarità con il modo in cui un server sarebbe in grado di nascondere una costante di pepe globale, ma la mia opinione è che prima o poi un hacker che è penetrato nel server capirà come catturare il valore di pepe. Per rendere un valore del pepe totalmente sicuro richiederebbe un hardware speciale. Un modo per farlo sarebbe usare una scheda FPGA installata nel server. L'FPGA conterrebbe il codice utilizzato per eseguire l'hash incluso il valore di pepe e tutti i calcoli dell'hash si verificano all'interno dell'FPGA. Con l'FPGA, la programmazione può essere una funzione a senso unico. Il pepe può essere programmato ma non è possibile inviare istruzioni per leggerlo nuovamente. Il pepe sarebbe stato conservato su un pezzo di carta chiuso in una cassaforte. Se il pepe è composto da 128+ bit generati casualmente, non ci sarebbe modo pratico per determinarlo.
Non sono sicuro di quanto sarebbe pratico in quanto aumenterebbe il costo dell'hardware del server.

1
Brian Sparks