C'è qualche rischio per la sicurezza nell'archiviazione delle varianti hash delle password?

16

Ad esempio, se ipoteticamente un requisito applicativo fosse quello di dire agli utenti quando la loro password poteva essere fallita perché Caps-lock era attivo, e ipoteticamente non c'era modo per l'applicazione di sapere che Caps-Lock era attivo, è esiste un rischio intrinseco di sicurezza nella memorizzazione di una password con hash e una versione hash "caps lock" di una password in modo che una password non riuscita possa essere confrontata anche con la versione "caps lock"?

Se un database contenente account utente con questa configurazione è stato violato, l'esistenza dell'hash della password "caps lock" oltre al normale hash della password renderebbe le password più vulnerabili di quanto sarebbero altrimenti?

Si noti che questo è un ipotetico e mi interessa più le implicazioni sulla sicurezza che se questa sia una buona pratica di programmazione.

    
posta Joe M. 09.05.2012 - 22:39
fonte

6 risposte

6

Un altro approccio, se desideri consentire diverse varianti della password.

Quando un utente accede alla vostra applicazione, normalmente otterreste una versione in chiaro della password (si spera su SSL) e poi la cancellate e la confrontate con il vostro valore di hash memorizzato.

Non è quindi necessario memorizzare diverse versioni di hash. Puoi memorizzare un hash della password , ma quando l'utente prova ad accedere, esegui tali trasformazioni sulla password fornita dall'utente al momento del login e poi cancellane quelle varianti. per esempio. se la password fornita non è stata confrontata con l'hash, applicare la trasformazione caps-lock , hash e quindi ricontrollare con l'hash memorizzato. Se corrisponde allora puoi decidere di dare all'utente l'accesso alla tua applicazione.

In questo modo memorizzi solo una versione (canonica) dell'hash, ma permetti diverse permutazioni della stessa password.

In termini di scenari di attacco:

  • Attacco offline contro gli hash delle password: rimane lo stesso
  • Attacco online che cerca di autenticare con password diverse - questo diventerà più facile in relazione al numero di possibili permutazioni

Tuttavia, in genere dovrebbe essere più facile limitare il numero di possibili forza bruta remota o tentativi di indovinare la password per renderlo sufficientemente difficile. Puoi leggere ulteriori informazioni su alcune tecniche qui che probabilmente dovresti implementare comunque.

Sarei ancora molto attento a quali possibili permutazioni sono supportate ea misurare quanto potrebbero ridurre l'entropia della password, ovviamente, ma almeno non è necessario memorizzare più versioni con hash per farlo.

    
risposta data 10.05.2012 - 07:58
fonte
8

Domanda interessante. Immagino dipenda da quale e quante versioni stai memorizzando. La principale preoccupazione nel farlo è quanto stai riducendo lo spazio di ricerca / entropia.

Se, ad esempio, la versione caps-lock della password è una versione maiuscola della password, quindi memorizzandola in questo modo, stai riducendo l'entropia della password. L'attaccante in questo caso deve solo cercare usando la versione caps-lock usando solo caratteri maiuscoli. Questo dà loro un lavoro significativamente più semplice.

Se, tuttavia, la versione caps-lock è semplicemente un caso-inverso delle lettere, vale a dire la normale password == aXbJklMP e la versione caps-lock == AxBjKLmp , quindi si ' probabilmente non riducendo enormemente lo spazio di ricerca. Ci sono ancora due password possibili invece di una, rendendo la ricerca il doppio delle probabilità di trovare una di quelle password anche se ...

    
risposta data 09.05.2012 - 23:01
fonte
4

Espansione sul mio commento precedente:

If the two stored hashes (with and without the caps lock transformation) are the same, we can know that the user has no letters in their password. (Or at least has no lower case letters in their password depending on how you do the transformation.)

Dato che Mac e Windows (e Linux) gestiscono il blocco dei tappi in modo diverso, è necessario memorizzare due varianti dell'hash di trasformazione del blocco maiuscole: inversione del caso (Windows / Linux) e tutto maiuscolo (Mac). Ora possiamo determinare ancora di più sulla password dagli hash.

  1. Se tutti e tre gli hash sono uguali, l'utente non ha lettere (maiuscole o minuscole) nella sua password.
  2. Se l'hash di trasformazione di Windows è diverso ma l'hash di trasformazione Mac è lo stesso dell'hash principale, l'utente ha lettere maiuscole nella loro password ma nessuna lettera minuscola.
  3. Se tutti e tre gli hash sono diversi, l'utente ha entrambe le lettere maiuscole e minuscole nella loro password.

Un altro pensiero: è sicuro applicare lo stesso sale a tutte e tre le varianti? Anche se penso che dovrebbe essere, non vedo alcun vantaggio significativo nel farlo. Se applichi un sale diverso a tutti e tre gli hash, I pensa che le perdite di informazioni di cui sopra siano negate. Nota che non sono un crittografo, anche se non dovrebbero esserci perdite di informazioni quando si eseguono tre password correlate e possibilmente identiche con tre diversi sali, potrebbe essere necessario un tempo più lungo per essere sicuro.

Altri problemi:

Poiché abbiamo tre varianti di hash della password che devono essere controllate ogni volta che un utente sta effettuando l'accesso, è necessario calcolare tutti e tre gli hash. Se si utilizza bcrypt (o simile) con un numero appropriato di cicli di hashing, si vorrà ridurre quel numero di cicli in modo che il tempo impiegato sia circa 1/3 del vecchio valore. (Partendo dal presupposto che puoi impostare il numero di round più alto che puoi gestire e ora devi calcolare tre volte il numero di hash per accesso.)

Il motivo per cui è necessario calcolare tutti e tre gli hash anche se il primo o il secondo corrispondono è che, se non lo fai, abilita l'enumerazione delle credenziali tramite gli attacchi temporali. In teoria, per prevenire l'enumerazione delle credenziali è necessario fornire esattamente la stessa risposta, se l'utente non esiste o lo fa, ma la password è sbagliata. Se restituisci una risposta identica per entrambi i casi ma impiega millisecondi quando l'utente non esiste e un secondo intero quando l'utente esiste, hai comunque abilitato l'enumerazione delle credenziali.

Tutto sommato, penso che dovrebbe essere relativamente sicuro se usi diversi sali per tutti e tre gli hash, calcola sempre tutte e tre le variazioni della password fornita e riduci il numero di round in modo che i tempi siano ridotti di 1/3.

Tuttavia, potrebbe essere più semplice memorizzare un solo hash, controllare la password fornita dall'utente per le lettere minuscole e se non ce ne sono e l'hash non corrisponde, suggerire loro che potrebbero avere il blocco maiuscole.

Ultimi pensieri

Non è necessario memorizzare tre diversi hash come suggerito in precedenza se si prevede di accettare la trasformazione in stile Mac. È sufficiente mettere tutte le password in maiuscolo prima di eseguire l'hash e archiviare solo la versione maiuscola. Ciò impedisce anche gli attacchi temporali poiché è sufficiente calcolare un hash per accesso.

In questo modo hai ridotto il numero di possibili lettere / numeri / simboli che le persone possono utilizzare per 26, quindi potresti consigliare agli utenti di utilizzare una password leggermente più lunga per compensare.

    
risposta data 10.05.2012 - 11:39
fonte
3

Succede che memorizzare entrambi gli hash, o invertire l'effetto capslock e provare entrambe le versioni, riduce davvero la sicurezza di un fattore che è tra 1 e 2 . È un po 'complicato da vedere, quindi definiamo le cose chiaramente.

Sto usando il concetto di capslock inverso di capslock. Se l'effetto capslock è davvero un effetto tutto-è-maiuscolo, non dovresti mai accettare o memorizzare quella versione tutto maiuscola; invece, restituire un avviso come @ D.W. suggerisce.

Suppongo che tu usi una funzione hash lenta e salata come bcrypt (se tu allora non è un problema più grande e dovresti prima aggiustarlo). La parte "lenta" è configurabile con un numero di iterazione che si genera il più possibile, in base a due vincoli: il budget della CPU per l'hashing (a seconda di quanto CPU gratuita e quante connessioni client al secondo) e pazienza dell'utente (che non è mai molto alta). Il costo per l'attaccante è direttamente proporzionale al numero di iterazioni. Se memorizzi due valori hash (per la versione "normale" e "capslock" della password), entrambi devono avere il loro valore.

Quando "provi" la password inviata dall'utente e poi "riprova" con una versione capslock della stessa password, allora stai effettivamente eseguendo l'hashing due volte, quindi c'è un sovraccarico sui tuoi vincoli. In media, lo sforzo della CPU sarà moltiplicato per 1 + f , dove f è la proporzione di password errate ( f = 0 se tutte le gli utenti digitano perfettamente, f è molto vicino a 1 se tutti gli utenti sono scimpanzé che devono provare una dozzina di volte prima di digitare correttamente la loro password). Inoltre, ogni volta che devi provare la versione capslock della password, l'utente deve attendere ancora due volte prima di ottenere l'accesso (se la versione capslock risulta essere corretta) o essere ignorato (se la password è veramente sbagliata, capslock o no). In una certa misura, gli utenti medi hanno una maggiore comprensione dei ritardi quando ritengono che sia colpa loro, perché hanno sbagliato, ma non ci conterei.

L'effetto netto è che il test per due versioni della password aumenta il costo di un fattore compreso tra 1 e 2; corrispondentemente, devi diminuire il numero di iterazioni di quel fattore e l'efficacia dell'attaccante viene moltiplicata per quel fattore.

Questo è davvero un compromesso tra l'esperienza dell'utente (che in molti casi significa "costi di helpdesk") e la sicurezza. Se possibile, è probabilmente meglio rilevare che il capslock è premuto e avvisare l'utente prima che la password venga inserita; tuttavia, ciò potrebbe rivelarsi difficile (conosco un sito che riesce a farlo quando il client è Internet Explorer, ma non riesce con Chrome e Firefox, ma emette avvisi visibili per ogni lettera maiuscola, il che è piuttosto negativo perché gli avvisi sono visibili da lontano, quindi è una perdita di informazioni sulla password).

    
risposta data 28.10.2012 - 18:09
fonte
2

@Yoav Aner l'ha completamente inchiodato all'impatto sulla sicurezza della memorizzazione sia dell'hash della password che dell'hash del capslock della password. Inoltre, @ cx42net ha un suggerimento brillante: usa Javascript sul lato client per verificare se Capslock è attivo e, in tal caso, avvisa l'utente.

Non ho nulla da aggiungere a quelle risposte, quindi lasciatemi provare ad espandere un approccio diverso (ispirato da un suggerimento di @Yoav Aner). Per questo, ho bisogno di sapere se funziona a capslock facendo in maiuscolo tutte le lettere che scrivi, o se funziona invertendo il caso di tutte le lettere che scrivi. Sembra che la risposta dipenda dal particolare cliente, quindi ti darò una risposta in entrambi i modi; potrebbe essere necessario applicarli entrambi, se non si è sicuri del tipo di sistema utilizzato dal client.

Se il Capslock supera tutte le lettere: Salva solo l'hash della password nel tuo database. Quando si riceve una password P candidata dal client, è possibile eseguire i seguenti passaggi sul server per convalidare la password:

  1. Calcola hash (P) e verifica se corrisponde all'hash della password dell'utente (come memorizzato nel database). In caso affermativo, contrassegnare l'utente come autenticato; hai finito. Altrimenti, continua con il passaggio 2.

  2. Controlla se P contiene lettere minuscole. Se sì, rifiuta il tentativo di autenticazione. In caso contrario (se tutte le lettere in P sono in maiuscolo), rifiuta il tentativo di autenticazione ma avverti l'utente di verificare se è stato attivato il capslock e chiedere loro di riprovare.

Questo schema non ha alcun impatto negativo sulla sicurezza del sistema in alcun modo.

Se il capovolgimento inverte il caso di tutte le lettere: Salva solo l'hash della password nel tuo database. Quando si riceve una password P candidata dal client, è possibile eseguire i seguenti passaggi sul server per convalidare la password:

  1. Calcola hash (P) e verifica se corrisponde all'hash della password dell'utente (come memorizzato nel database). In caso affermativo, contrassegnare l'utente come autenticato; hai finito. Altrimenti, continua con il passaggio 2.

  2. Sia P 'il risultato di invertire il caso di tutte le lettere in P. Compute Hash (P) e vedere se corrisponde all'hash della password dell'utente (come memorizzato nel database). In caso affermativo, contrassegnare l'utente come autenticato, ma avvisarlo per verificare se è stato attivato il Caps Lock. Altrimenti, rifiuta il tentativo di autenticazione.

Questo schema riduce lo sforzo necessario per un attacco di indovinare la password online di un fattore 2; non un grande affare. Non riduce affatto la sicurezza del sistema contro gli attacchi offline.

Addendum: ecco un'idea pazzesca che potresti provare se il Capslock supera tutte le lettere. Non lo consiglio, ma lo dico solo perché è così pazzo.

Archivia solo l'hash della password nel tuo database. Quando si riceve una password P candidata dal client, è possibile eseguire i seguenti passaggi sul server per convalidare la password:

  1. Calcola hash (P) e verifica se corrisponde all'hash della password dell'utente (come memorizzato nel database). In caso affermativo, contrassegnare l'utente come autenticato; hai finito. Altrimenti, continua con il passaggio 2.

  2. A questo punto, verificherete l'ipotesi che forse P è la versione in maiuscolo della password dell'utente. Controlla se P ha lettere minuscole. Se P ha lettere minuscole, rifiuta il tentativo di autenticazione e si ferma. Altrimenti, continua con il passaggio 3, dove continuerai a verificare questa ipotesi.

  3. Proverai a sbloccare il blocco P, e poi a controllare la versione up-capslocked. Sfortunatamente, ci sono molti modi per sbloccare P, quindi dovrai provarli tutti. In particolare, supponiamo che P abbia lettere nelle posizioni n , con tutte quelle lettere in maiuscolo. Prova tutti i 2 sottoinsiemi n di quelle posizioni. Per ogni sottoinsieme, sia P 'il risultato di prendere P e quindi le lettere minuscole solo in quel sottoinsieme di posizione; calcolare Hash (P '); controlla se Hash (P ') corrisponde alla password con hash dell'utente; se lo fa, contrassegna l'utente come autenticato e avvisale di disattivare Capslock; altrimenti proseguire fino al prossimo sottogruppo. Se nessun sottoinsieme ha esito positivo, rifiuta il tentativo di autenticazione.

Questo è abbastanza folle, per tutti i tipi di ragioni. Riduce la sicurezza degli attacchi di indovinare online in modo abbastanza sostanziale (di un fattore 2 n , per le password con lettere n ). Non riduce la sicurezza degli attacchi di induzione offline. Ma aumenta anche significativamente la complessità del server. E date le risposte migliori menzionate altrove, non sembra esserci alcuna ragione per usare questo pazzo schema.

    
risposta data 10.05.2012 - 08:21
fonte
1

Non penso che sia necessario e inoltre, può ridurre la sicurezza della tua applicazione.

Per la parte necessaria, non so come identifichi il tuo utente, ma se si tratta di un'autenticazione client / server e il client ti invia la password in chiaro al server (il server, quindi, hash la password per confrontare con il database), puoi controllare la maiuscola qui:

// in the server :
// $password contains the original, clear password
$up_pass = invertcase($password); // I'll explain invertcase later
if (hash_and_find_pwd_in_db($password) == null) {
    if ($up_pass == $password) {
        return "Did you have caps lock enabled?";
}

(Nota sulla sicurezza: la sicurezza dello schema precedente presuppone l'implementazione di hash_and_find_pwd_in_db() tagliando la password e confrontandola con un valore hash memorizzato nel database, in questo modo il database memorizza solo gli hash delle password, non le password cleartext.)

Puoi sempre controllare usando javascript se il Capslock è abilitato , ma ancora, se JS è disabilitato, questo non funzionerà.

Informazioni sulle prestazioni: immagina di avere una versione "maiuscola", una versione "minuscola", ecc. ecc. Dovrai controllare l'hash della password originale, rispetto a quella corretta, se non viene trovata, avrai ad esso il database tante volte quante sono le alternative che hai. Solo per far sapere all'utente che ciò che ha inserito non è valido per un motivo specifico. Sono sicuro che non è affatto efficiente.

Ora, come ha detto @Yoav Aner, scrivendo aXbJklMP nella modalità di blocco maiuscole risulterà in questa stringa: AxBjKLmp . Ciò significa che dovrai implementare una funzione invertcase che modifica il caso di ogni lettera in modo che corrisponda all'ipotetica modalità di blocco maiuscole, senza alcuna certezza.

Riguardo la parte protetta, @Yoav Aner ha risposto perfettamente:)

    
risposta data 10.05.2012 - 07:58
fonte

Leggi altre domande sui tag