Autenticazione sicura: estensione parziale del tasto sul lato client ... si prega di rivedere / criticare la mia idea

5

Sto cercando di capire quale sarebbe il sistema di autenticazione "perfetto" per un sito web.

Da un lato, sappiamo che gli algoritmi di hashing semplici possono essere forzati o incrinati in altri modi. Quindi perché MD5 non è più raccomandato. La migliore soluzione per l'archiviazione sicura delle password, a quanto pare, si avvale di un allungamento delle chiavi in combinazione con la salatura (cioè utilizzando PBKDCF2, bcrypt o scrypt). Per coloro che non ne hanno sentito parlare, l'allungamento delle chiavi implica che un algoritmo di hash verrà calcolato attraverso molte iterazioni (non solo una volta), facendo sì che ogni tentativo di forza bruta prenda una quantità di tempo irragionevole per il calcolo.

Ora, se gli utenti si registrano, autenticano o modificano la loro password e il server utilizza la chiave che si estende per memorizzare la password, garantisce una protezione adeguata della password, ma lascia aperta la porta per gli attacchi DoS. Soprattutto, un hacker potrebbe invaderlo con tentativi di autenticazione con password casuali, e il server potrebbe soffocare sul calcolo di tutte quelle iterazioni per tutti quei tentativi.

Sto cercando di ottenere il meglio da entrambi i mondi: archiviazione sicura delle password con stretching chiave, senza la porta DoS aperta. Ecco la mia idea, e voglio sapere se sto supervisionando qualcosa, o se c'è qualche problema nella mia logica ... a volte, quando sei troppo vicino al problema ...

L'idea è:

  1. CLIENT-SIDE: l'utente del sito web inserisce nome utente, password

  2. CLIENT-SIDE: il sito Web utilizza la richiesta AJAX sul server per recuperare il numero di sale e il numero di iterazioni associate al record dell'utente (in base alla corrispondenza del nome utente)

  3. CLIENT-SIDE: Autenticazione Passaggio 1. Il sito web calcola, sul computer client con Javascript, tutte le iterazioni di hashing MINUS ONE (spiegherò perché dopo). Il calcolo viene eseguito utilizzando un algoritmo ben noto, come PBKDF2, bcrypt o scrypt. Il sito Web invia il risultato al server.

  4. SERVER-SIDE: Autenticazione Passaggio 2. Il server riceve lo username + la password hash (meno un'iterazione). Esegue l'ultima iterazione (con PBKDF2, bcrypt o scrypt) Confronta con il valore memorizzato per determinare se la combinazione è corretta. Restituisce la risposta al sito Web.

Ora, perché tutte le iterazioni meno uno? Se un hacker ottiene una copia del database e il server si aspetterebbe che venisse fornita una password completamente hash, sarebbe equivalente a memorizzare le password in testo normale. Hacker copia e incolla l'hash e usa il servizio di autenticazione. Pertanto, non possiamo restituirlo direttamente.

Tuttavia, poiché teoricamente non è possibile "invertire" l'hashing, se il server accetta solo un hash iterato n-1 significa che l'hacker non può indovinare quale sia l'iterazione precedente, in base a ciò che vediamo nel database. È corretto?

Alla fine, la maggior parte del lavoro viene eseguita sul lato client (il server esegue solo una iterazione), eliminando la minaccia DoS, ma abbiamo anche le password memorizzate con il key-stretching completo con salt, un pratica più sicura.

Mi manca qualcosa? Questo sarebbe un modo ideale per implementare un sistema di autenticazione? Fammi sapere! Mi sto solo chiedendo se mi manca qualcosa qui ...

    
posta hbCyber 27.09.2013 - 07:17
fonte

4 risposte

4

L'hashing sul lato client funziona concettualmente. Il problema, tuttavia, è quello di potere . In un contesto Web, il client utilizza Javascript e Javascript è debole per il calcolo di attività intensive. Il client utilizza già un sistema che può avere una CPU relativamente piccola (potrebbe essere uno smartphone economico, ad esempio), ma Javascript aggiunge il proprio overhead, che è enorme (perché è interpretato, difficile da JIT , e manca di tipi decenti di interi). Come stima approssimativa, l'hashing lato client in Javascript sarà da 20 a 40 volte più lento dell'hash della password su un server decente.

Purtroppo, la pazienza dell'utente non si allunga; l'utente tollera uno o due secondi di ritardo, non di più. Pertanto, quando si utilizza l'hashing sul lato client, è necessario utilizzare meno iterazioni rispetto a quando si utilizza l'hashing sul lato server, il che indebolisce l'intera immagine.

Oppure, detto altrimenti, finché gestisci il processo di login di non più di venti utenti al secondo , l'hashing sul lato server ti consentirà di utilizzare più iterazioni rispetto all'hash sul lato client, e quindi meglio per sicurezza.

Se il client utilizza un'applet Java , è molto più potente; il fattore "20x" diventa "3x". Ma le applet Java non sono più di moda e non funzionano su tablet e smartphone. I client mobili con un'app dedicata possono far rivivere il concetto di hashing della password sul lato client.

Per quanto riguarda i dettagli , il modo migliore è di non "rimuovere una iterazione" dall'algoritmo, ma di aggiungere un hash in più: gli algoritmi crittografici sono animali complessi e sebbene la funzione di hashing della password sia utilizzata internamente "iterazioni", non usano necessariamente iterazioni solo . Ad esempio, non è possibile rimuovere facilmente "l'ultima iterazione" di bcrypt e ottenere un risultato parziale da trasmettere al server. Quindi, invece, fai tutte le iterazioni sul client, invia il risultato R al server, e il server memorizza sia il sale, sia h (R) per qualche funzione di hash h (ad es. SHA-256).

    
risposta data 27.09.2013 - 13:11
fonte
2

SRP consente già l'allungamento dei tasti sul lato client perché ha un KDF sul lato client. Se sei così incline, puoi passare 15 minuti di cicli di masterizzazione mentre allunghi la chiave, ogni volta che esegui l'accesso, senza influire sulle prestazioni del server.

Questo è solo uno dei molti vantaggi.

    
risposta data 27.09.2013 - 17:30
fonte
0

Un difetto che posso vedere è che, poiché si sta eseguendo l'iterazione n-1 sul lato client, l'uso di bcrypt / scrypt / PBKCDF non ha senso. Poiché l'uso di questi algoritmi è quello di rendere il cracking delle password che richiede tempo e il calcolo intensivo. Nel presente scenario, un utente malintenzionato avrà prontamente l'hash dell'iterazione n-1 e richiederà ulteriormente un'altra iterazione per indovinare la password. Che sarebbe banale per qualsiasi attaccante e, a mia conoscenza, eseguito su una semplice macchina desktop.

Una possibile soluzione per prevenire DoS è, se qualcuno (utente malintenzionato) vuole accedere all'account, dopo un certo numero di tentativi di soglia è possibile impedire all'utente di accedere per un certo periodo di tempo e continuare ad aumentare in modo esponenziale. Ad esempio, lascia che i tentativi di soglia siano 3. Se un utente con nome utente 'user123' sta effettuando l'accesso, (s) inserisce 3 password errate, dopo di che puoi bloccare l'account per 5 secondi. Se di nuovo c'è un tentativo sbagliato dopo 5 secondi, puoi bloccare i conti per 10 secondi e così via.

In questo modo ti assicuri che un utente non stia tracciando la tua risorsa e rendendo qualsiasi attacco bruteforce che richiede tempo e che alla fine non è fattibile.

Modifica Un altro problema con questo approccio è che stai inviando il sale al lato client. Il sale è usato per rendere difficile la forzatura bruta delle password. Nello scenario attuale, l'attaccante avrà anche il sale corrispondente al nome utente facilmente disponibile.

Inoltre, se il client disabilita javascript, non sarà in grado di accedere al sito web. Ma questo potrebbe non essere un grosso problema, dato che i siti Web moderni dipendono strongmente da javascript e richiedono che siano abilitati sul client.

    
risposta data 27.09.2013 - 09:36
fonte
0

Con una funzione di derivazione dei tasti lenta si vogliono raggiungere due obiettivi:

Impedisce a un utente malintenzionato di accedere al

L'hash iterato lato client, può essere visto come una sostituzione della stessa password, che viene inviata al server e verrà sottoposta a hash e memorizzata. Se un utente malintenzionato può scoprire questa sostituzione della password, potrebbe effettuare il login. Dato che l'output dell'hash pre-iterato (BCrypt) è di circa 60 caratteri (con 7 caratteri costanti e 21 caratteri salt saltati), ci sarebbero ancora più di 1E50 combinazioni da testare, quindi la forzatura bruta sembra non praticabile.

Impedisce a un utente malintenzionato di ottenere la password originale, che può utilizzare su altri servizi Web

Per scoprire la password originale, un utente malintenzionato dovrebbe comunque eseguire tutte le iterazioni. Quindi le iterazioni eseguite sul lato client rallenteranno gli attacchi del dizionario (test delle password usate spesso).

Quindi in realtà il tuo schema sembra funzionare, almeno non riesco a vedere un difetto evidente. C'è un problema con BCrypt, però, questo algoritmo usa la password originale e il sale in ogni iterazione, quindi non si può fare più un'iterazione, invece si dovrebbe calcolare un hash aggiuntivo sul server.

Per favore, leggi anche la risposta di Thomas Pornin, ci sono motivi pratici per fare il lato server di hashing (e lui è l'esperto).

    
risposta data 27.09.2013 - 13:39
fonte

Leggi altre domande sui tag