Autenticazione degli utenti nelle app Web senza inviare la password: qualcuno può suggerire miglioramenti?

1

Mi sono interessato all'implementazione del metodo di autenticazione per un'app Web che viene eseguita nei browser moderni, senza dover inviare la password sul filo.

Qualcuno può suggerire miglioramenti o persino dirmi se sto sbagliando o meno.

L'autenticazione viene eseguita tramite una connessione HTTP non protetta utilizzando AJAX.

Le mie attuali conoscenze sull'implementazione di un protocollo di autenticazione

Il server ha una password utente che è stata sottoposta a hash con bcrypt e archiviata durante la registrazione.

L'utente inserisce id e password . Un XMLHttpRequest viene inviato al server per iniziare l'autenticazione, X-R1 è un numero intero casuale creato sul client.

GET /auth/{id} HTTP/1.1
X-R1: 123412341234
  1. Il server ottiene i valori.

    • ServerPassword - gli utenti bycrpt hanno cancellato la password dal database delle password

    • X-Salt - estrae il sale da ServerPassword

    • X-R1 - dal client nell'intestazione della richiesta

    • X-R2 - numero intero generato casualmente sul server.

  2. Il server crea valori

    • X-Session - chiave di sessione, concatenando X-R1 + X-R2 + id allora un solo modo esegue l'hash di questa stringa

    • Verifier - segreto condiviso, concatenazione di X-R1 + X-R2 + ServerPassword e quindi hashing unidirezionale di questa stringa.

    • Salva questi valori in un archivio di sessioni.

Risposta del server.

HTTP/1.1 202 ACCEPTED
X-R2: 432143214321
X-Salt: $2a$10$rBV2JDeWW3.vKyeQcM8fFO
X-Session: 92429d82a41e930486c6de5ebda9602d55c39986
  1. Il client ottiene valori

    • X-R1 - stesso valore di prima dell'invio della richiesta.

    • ClientPassword - testo semplice, quale utente ha inserito.

    • X-R2 - dall'intestazione del server inviato

    • X-Salt - dall'intestazione inviata dal server.

  2. Il cliente crea valori

    • HashedPassword - creato utilizzando un'implementazione JavaScript di bcrypt utilizzando ClientPassword e X-Salt

    • Verifier - Concatenamento di X-R1 + X-R2 + HashedPassword e quindi un modo di hashing di questo valore. Il client utilizza un'implementazione JavaScript di bcrypt per hash la password che l'utente ha immesso con la stringa di X-Salt .

Ora il client e il server pensano entrambi di avere lo stesso verificatore per confermare che questo client invia un'ulteriore richiesta, ma questa volta esegue l'hashing delle intestazioni e del corpo della richiesta con il verificatore e quindi aggiunge "X-Auth" alle intestazioni con hash risultante.

POST /auth/{id} HTTP/1.1
X-Session: 92429d82a41e930486c6de5ebda9602d55c39986
X-Auth: ad801198a9fab4e4ef79eb97624a4bf9c78b450a

Il server ora ricerca X-Sessions nel suo archivio di sessioni. Fa lo stesso hashing delle intestazioni e del corpo della richiesta e poi controlla se l'hash corrisponde al valore di X-Auth , in tal caso il server presuppone che il client sia autorizzato e risponda di conseguenza.

HTTP/1.1 200 OK

Il client sa che il server ha lo stesso Verifier e lo memorizza in localStorage usando il valore di X-Session per la chiave, per ulteriori richieste.

Preoccupazioni

Sono uno sviluppatore medio e nessun esperto di crittografia e dalla mia comprensione non riesco a vedere eventuali problemi che potrebbero verificarsi con questo metodo.

Riesco a vedere i grandi vantaggi, come ad esempio:

  1. La password non viene mai inviata tramite cavo. Impedisci al MITM di ottenere la tua password.

  2. MITM non può modificare la richiesta poiché è stata sottoposta a hashing con il verificatore e quindi inviata.

  3. Il server non ha bisogno di usare bcrypt ogni volta che un utente vuole autenticarsi.

posta jamcoope 02.10.2013 - 16:54
fonte

3 risposte

6

The authentication is done over an unsecured http connection using AJAX.

Ti fermo qui. Se il codice Javascript in esecuzione sul lato client è andato su HTTP non protetto, allora quel codice potrebbe essere stato alterato in transito da qualsiasi mezzo competente Man-in-the-Middle attacker. Può quindi fare un sacco di cose cattive, come, ad esempio, l'invio di una copia della password dell'utente a un server controllato da un malintenzionato.

La crittografia lato client in Javascript funziona solo se il suddetto javascript si trova su un collegamento sicuro, ad esempio HTTPS. E se hai quel link, allora perché ti infastidirebbe ulteriormente?

Oltre a ciò, ciò che descrivi non ha nulla di "SRPish". SRP è un protocollo di scambio di chiavi autenticato con password , il che significa che garantisce l'immunità contro l'attacco di dizionario offline, cosa che non è possibile essere ottenuto con strumenti di crittografia simmetrici come le funzioni hash e bcrypt. Al massimo, bcrypt concederà resistenza agli attacchi del dizionario offline, il che significa che un intercettatore, spiando una connessione, potrebbe imparare abbastanza da "testare le password a casa" ma soffrirà per ogni test.

SRP fa "meglio" con qualche matematica in più. Vedi RFC . Ci sono esponenziati modulari in là.

SRP-with-TLS ha senso solo perché funziona direttamente a livello SSL, è fatto dal browser, e usa un'implementazione che è già sul lato client. Quando il browser non implementa SRP a livello SSL, si ritorna alla configurazione "normale" con il normale SSL (con un certificato server) e l'invio della password utente "così com'è" tramite SSL.

    
risposta data 02.10.2013 - 17:07
fonte
2

Si sta inviando l'hash delle password sul cavo al server. Se il tuo database, che memorizza hash e sale, viene violato, l'hacker invierà solo il valore richiesto utilizzando il proprio codice JavaScript e ingannare il server.

Quindi se lo fai su https, inviando password al server e facendo hashing, c'è un approccio migliore. Dato che SSL / TLS è sicuro per garantire che solo il server sia in grado di vedere la password e tutti devono fidarsi del server per fare il proprio bit correttamente (cioè generare hash salato dalla password e confrontarlo con il valore db). E se questo è il tuo approccio, sono sicuro che non hai bisogno di reinventare la ruota. Qualunque sia la libreria che stai usando, questa implementazione sarà lì.

    
risposta data 20.05.2014 - 08:24
fonte
1

Se si invia una versione hash della password per l'autenticazione, l'hash diventa la password. L'ho visto prima e non funziona.

  • L'hashing non ha lo scopo di prevenire un attacco Man-in-the-middle, è usato per impedire che un database rubato diventi un elenco di password.
  • Sembra che tu stia perdendo il sale sul lato server, il che significa che passare gli hash nel tuo database è più facile
  • Un man-in-the-middle potrebbe modificare la risposta del server, impostando sia X-Salt che X-R2 sulla stringa vuota. Se hanno intercettato in precedenza X-R1, devono solo utilizzare la forza bruteforce della password dell'utente per passare l'hash (l'hashcode che il client invia al server dopo la risposta del server falsificato). Quindi torni al punto di partenza.

Stai cercando di implementare il tuo schema di crittografia, ed è fantastico per imparare come funziona questa roba. Non farlo in produzione. Non farlo. Centinaia di persone hanno trascorso anni a fare SSL / TLS. Usalo.

Vuoi qualcosa di simile invece di X-R1 e X-R2:

link

    
risposta data 03.10.2013 - 02:38
fonte

Leggi altre domande sui tag