Devo hash la password prima di inviarla al lato server?


110

Ho notato che la maggior parte dei siti invia le password come testo normale tramite HTTPS al server. C'è qualche vantaggio se invece di quello ho inviato l'hash della password al server? Sarebbe più sicuro?


5
@Jader Dias: So che non l'hai chiesto, ma non sarebbe più sicuro se lo hash, POI inviarlo tramite https. In effetti, potrebbe renderlo meno sicuro, dal momento che esponi il tuo sale. Inoltre, (parlando del mio rovescio qui), il mix di algoritmi potrebbe causare più collisioni di hash e renderlo più hackerabile.
Merlyn Morgan-Graham

@ Merlyn "hash collisions" buon punto!
Jader Dias

Gli algoritmi di missaggio non aumentano affatto la probabilità di collisione. Questo è il punto centrale di una funzione hash. Data qualsiasi entropia di input, restituisce un output che ha la stessa probabilità di trovarsi ovunque nel possibile spazio di output.
JJ

@JJ "La combinazione di algoritmi non aumenta affatto la probabilità di collisione." Mi piacerebbe davvero vedere una prova di questa affermazione. Lascia che ti fermi: questo è falso , in generale aumenta le collisioni. Posso facilmente costruire una funzione di hashing tale che h (x) non è costante 0 ma h (h (x)) = 0 per ogni x. Quindi dovresti fare riferimento al set esatto di algoritmi di hashing e al modo in cui li mescoli. Allora dovresti provare la tua dichiarazione. AFAIK anche per più SHA (con sale) questo è un problema aperto. E fondamentalmente crediamo che questo sia vero. La crittografia è difficile.
bizzarro

Risposte:


155

Questa è una vecchia domanda, ma ho sentito il bisogno di fornire la mia opinione su questo importante argomento. C'è così tanta disinformazione qui

L'OP non ha mai menzionato l'invio della password in chiaro su HTTP - solo HTTPS, tuttavia molti sembrano rispondere alla domanda di inviare una password su HTTP per qualche motivo. Detto ciò:

Credo che le password non dovrebbero mai essere conservate (figuriamoci trasmesse) in testo normale. Ciò significa che non viene conservato su disco o anche in memoria.

Le persone che rispondono qui sembrano pensare che HTTPS sia un proiettile d'argento, ma non lo è. Certamente aiuta molto, tuttavia, e dovrebbe essere utilizzato in qualsiasi sessione autenticata.

Non c'è davvero bisogno di sapere cosa sia una password originale. Tutto ciò che è richiesto è un modo affidabile per generare (e rigenerare in modo affidabile) una "chiave" di autenticazione basata sul testo originale scelto dall'utente. In un mondo ideale, questo testo dovrebbe generare immediatamente una "chiave" eseguendo l'hashing utilizzando sale irreversibile. Questo sale dovrebbe essere univoco per la credenziale utente generata. Questa "chiave" sarà ciò che i tuoi sistemi useranno come password. In questo modo, se i tuoi sistemi verranno mai compromessi in futuro, queste credenziali saranno utili solo contro la tua stessa organizzazione e in nessun altro luogo in cui l'utente è stato pigro e ha utilizzato la stessa password.

Quindi abbiamo una chiave. Ora dobbiamo ripulire qualsiasi traccia della password sul dispositivo client.

Successivamente dobbiamo ottenere quella chiave per i tuoi sistemi. Non si dovrebbe mai trasmettere una chiave o una password "in chiaro". Nemmeno su HTTPS. HTTPS non è impenetrabile. In effetti, molte organizzazioni possono diventare un MITM affidabile, non dal punto di vista degli attacchi, ma per eseguire ispezioni sul traffico per implementare le proprie politiche di sicurezza. Questo indebolisce HTTPS e non è l'unico modo in cui accade (come ad esempio i reindirizzamenti agli attacchi HTTP MITM). Non dare mai per scontato che sia sicuro.

Per aggirare questo problema, abbiamo hash la chiave con un nonce una tantum. Questo nonce è unico per ogni invio di una chiave ai tuoi sistemi, anche per la stessa credenziale durante la stessa sessione se devi inviarla più volte. È possibile annullare questo nonce una volta arrivato nei propri sistemi per ripristinare la chiave di autenticazione e autenticare la richiesta.

A questo punto lo farei in modo irreversibile un'ultima volta prima che venga memorizzato in modo permanente nei tuoi sistemi. In questo modo puoi condividere le credenziali con le organizzazioni partner ai fini di SSO e simili, pur essendo in grado di dimostrare che la tua organizzazione non può impersonare l'utente. La parte migliore di questo approccio è che non condividi mai nulla generato dall'utente senza la sua autorizzazione.

Fai più ricerche, poiché c'è di più di quanto io abbia divulgato, ma se vuoi fornire una vera sicurezza ai tuoi utenti, penso che questo metodo sia attualmente la risposta più completa qui.

TL; DR:

Usa HTTPS. Password hash in modo sicuro, irreversibile, con un salt univoco per password. Fallo sul client: non trasmettere la password effettiva. La trasmissione della password originale dell'utente ai server non è mai "OK" o "Fine". Pulisci ogni traccia della password originale. Usa un nonce indipendentemente da HTTP / HTTPS. È molto più sicuro su molti livelli. (Risposta a OP).


25
Ho appena controllato Gmail e Facebook: gli strumenti per sviluppatori di Chrome mi dicono entrambi POST con un messaggio con codifica URL contenente il mio nome utente e la password in testo semplice (non salato). Come / perché i grandi giocatori non usano il nonce salting sul client?
gremwell

18
Hai hash la chiave con un nonce e afferma di essere in grado di invertire il nonce sul lato server. Allora stai forzando l'hashish? O come si recupera un nonce quando si ottiene un hash = HASH (secret + nonce) HASH dovrebbe essere una funzione irreversibile. Hai implementato questo? Non credo che quello che spieghi sia fattibile. Potete creare un diagramma di flusso del protocollo?
Argento

19
Se non ti fidi di HTTPS, ogni singolo sforzo è inutile! Il tuo codice stesso viene spedito attraverso il filo e un utente malintenzionato può modificare / sostituire tutti i tuoi tentativi di proteggere la password in transito
Sajid Kalla

3
Un MitM in grado di riscrivere un certificato può riscrivere il nonce. O quello che ha detto Sajid.
leewz

4
Se sei preoccupato per MITM con HTTPS, che senso ha inviare un salt al client in modo che il client possa salare la password prima di ritrasmettere l'hash al server? Sembra inutile. Tanto vale fare un hash non salato al server, quindi utilizzare di nuovo un hash salt per eseguire l'hash sul server. Chiaramente, il client non può nemmeno essere il generatore del client-salt perché al prossimo login, sarebbe diverso e non calcolerebbe lo stesso hash lato server.
schiacciare il

24

Dal momento che è su HTTPS, va decisamente bene inviare la password senza hashing (su HTTPS non è testo in chiaro). Inoltre, se la tua applicazione dipende da HTTPS per mantenere i suoi contenuti protetti, allora è inutile hash la password prima di inviarla tramite HTTPS (cioè se un malintenzionato può decriptare i dati sul cavo, sei fottuto comunque)


5
Questo non dovrebbe essere un problema. Se il client utilizza un proxy, tutto ciò che il proxy vedrà sono i dati crittografati HTTPS. Se stai parlando di un attacco man-in-the-middle, un certificato configurato correttamente dovrebbe impedirlo.
Kiersten Arnold

7
@Jader: Nessuna quantità di giocherellare con i dati fermerà un attacco MITM, dal momento che può semplicemente trasmettere qualunque cosa ne derivi. Non importa se stai trasmettendo una password o un hash. È una questione completamente diversa.
David Thornley

2
Lo scopo di SSL (HTTPS = HTTP su SSL) è contrastare MITM.
yfeldblum

1
@carnold - MINTM - Che dire del reindirizzamento a http? La maggior parte delle persone l'avrebbe notato? sslstrip - securityfocus.com/brief/910
nate c

1
@Jader Dias stai cercando di fermare un problema che non esiste. HTTPS ferma questo problema, un hash lato client non aggiunge alcuna quantità di sicurezza. Non ci si può mai fidare del cliente.
torre

17

No, in effetti questa sarebbe una vulnerabilità. Se l'attaccante è in grado di ottenere l'hash dal database, potrebbe usarlo per autenticarsi senza bisogno di crackarlo. In nessun caso un utente o un utente malintenzionato deve essere in grado di ottenere una password hash.

Lo scopo dell'hashing delle password è aggiungere un ulteriore livello di sicurezza. Se un utente malintenzionato è in grado di ottenere l'hash e il sale dal database utilizzando SQL Injection o un backup non sicuro, deve trovare il testo normale forzandolo. John The Ripper è comunemente usato per rompere gli hash delle password salate.

Il mancato utilizzo di https è una violazione della Top 10 di OWASP: protezione del livello di trasporto insufficiente A9

EDIT: se nella tua implementazione calcoli un sha256(client_salt+plain_text_password)e poi calcoli un altro hash sul lato server, sha256(server_salt+client_hash)questa non è una grave vulnerabilità. Tuttavia, è ancora suscettibile di intercettare e riprodurre la richiesta. Quindi questa è ancora una chiara violazione di WASP A9. Tuttavia, questo utilizza ancora un digest del messaggio come livello di sicurezza.

La cosa più vicina che ho visto a una sostituzione lato client per https è un diffie-hellman nello scambio di chiavi in ​​javascript . Tuttavia, questo impedisce gli attacchi MITM attivi e quindi è fino a tecnicismo una violazione di OWASP A9. Gli autori del codice concordano sul fatto che questo non è un sostituto completo per HTTPS, tuttavia è meglio di niente e meglio di un sistema di hashing lato client.


4
In realtà lo farei di nuovo nel server, quindi modifica la tua risposta considerando questo scenario.
Jader Dias

@Rook utilizza lo scambio di chiavi diffie-hellman insieme a https è una soluzione "inutile"? (Voglio dire che possiamo usare solo https e diffie helman non aumentare la sicurezza imao)
Michel Gokan

@Michel Kogan uno scambio di chiavi DH può essere utilizzato in HTTP insieme ad altri strumenti.
torre

1
@Rook È una buona pratica applicare un hash sul server, quindi penso che dovresti aggiornare l'inizio della tua risposta per non ignorare l'hashing lato client, e solo allora menzionare che gli hash ei sali memorizzati del server non dovrebbero mai essere esposti.
Levente Pánczél

8

L'invio di un hash via cavo annulla completamente lo scopo dell'hash, perché un utente malintenzionato può semplicemente inviare l'hash e dimenticare la password. In poche parole, un sistema che autentica utilizzando un hash in chiaro è completamente aperto e può essere compromesso con nient'altro che lo sniffing della rete.


2
Sembra una stronzata totale ... In che modo un hash è meno sicuro di una password?
Levente Pánczél

1
Questo è vero solo per gli hash "stupidi". Considera questo: un server invia un salt S al client e il client esegue HASH (S + PASSWORD) e lo invia al server. Il server rispetta quell'hash specifico solo per la sessione corrente. Un utente malintenzionato può effettivamente inviare l'hash e dimenticare la password, ma SOLO PER LA SESSIONE CORRENTE. Quindi è più sicuro del testo normale.
Hello World,

Aggiornamento: l'autenticazione dell'accesso al digest è ancora più sofisticata: en.wikipedia.org/wiki/Digest_access_authentication
Hello World,

2
Giusto per essere chiari: quando dico "sconfigge lo scopo dell'hash" mi riferisco alla pratica comune e sicura di hashing delle password prima di memorizzarle in un database. Tuttavia, l'argomento sostiene che l'invio di un valore hash invece di una password non fa nulla per migliorare la sicurezza senza passaggi aggiuntivi.
Paul Keister,

Giusto per aggiungere a ciò che ha detto Paul: questo tipo di attacco è chiamato "replay attack" se qualcuno vuole saperne di più su di esso altrove.

5

La password in testo non crittografato non lascia mai (nemmeno quando si utilizza HTTPS) il client. Deve essere sottoposto a hashing irreversibile prima di lasciare il client poiché non è necessario che il server conosca la password effettiva.

L'hash e quindi la trasmissione risolvono i problemi di sicurezza per gli utenti pigri che utilizzano la stessa password in più posizioni (lo so). Tuttavia, ciò non protegge la tua applicazione in quanto hacker che ha ottenuto l'accesso al database (o in qualsiasi altro modo è stato in grado di mettere le mani sull'hash) poiché l'hacker potrebbe semplicemente trasmettere l'hash e chiedere al server di accettarlo.

Per risolvere questo problema potresti ovviamente semplicemente eseguire l'hash dell'hash ricevuto dal server e chiamarlo un giorno.

Il mio approccio al problema in un'applicazione web basata su socket che sto creando è che alla connessione al client il server genera un salt (stringa casuale da aggiungere prima dell'hashing) e lo memorizza sulla variabile socket, quindi trasmette questo hash al cliente. Il client prende la password dell'utente, l'ha hash, aggiunge il sale dal server e l'hashing del tutto, prima di trasmetterlo al server. Quindi viene inviato al server che confronta questo hash con l'hash (hash nel DB + salt). Per quanto ne so questo è un buon approccio, ma per essere onesti non ho letto molto sull'argomento e se mi sbaglio su qualcosa mi piacerebbe essere corretto :)


3

Usa HTTP Digest: protegge la password anche su http (ma il miglior utilizzo sarebbe http digest su https)

Wikipedia:

L'autenticazione dell'accesso al digest HTTP è uno dei metodi concordati che un server Web può utilizzare per negoziare le credenziali con un utente Web (utilizzando il protocollo HTTP). L'autenticazione del digest ha lo scopo di sostituire l'uso non crittografato dell'autenticazione di accesso di base, consentendo di stabilire in modo sicuro l'identità dell'utente senza dover inviare una password in chiaro sulla rete. L'autenticazione del digest è fondamentalmente un'applicazione di hashing crittografico MD5 con l'utilizzo di valori nonce per prevenire la crittoanalisi.

Collegamento: http://en.wikipedia.org/wiki/Digest_access_authentication

Se vuoi vedere un utilizzo "nella vita reale", potresti guardare phpMyID - un provider php openid che utilizza l'autenticazione http digest http://siege.org/phpmyid.php

.. oppure puoi iniziare dagli esempi di autenticazione php su http://php.net/manual/en/features.http-auth.php

Http digest rfc: http://www.faqs.org/rfcs/rfc2617

Dai miei test tutti i browser moderni lo supportano ...


HTTP Digest implementa ciò che intendevo in questa domanda, ma avremmo qualche vantaggio se usassimo HTTPS Digest (SSL + HTTP Digest)?
Jader Dias

Una differenza principale sarebbe che tutto viene inviato / ricevuto crittografato: le intestazioni http inviate e ricevute e la risposta html. Per qualcuno che cerca casualmente di "hackerare" ssl usando un attacco man-in-the-middle, il digest http sarebbe un motivo in più per fargli cercare un altro obiettivo più facile, o se sta registrando tutto il traffico catturato, le tue password sono ancora più sicure. Potrei aver frainteso la domanda, l'inglese non è la mia prima lingua.
vlad b.

L'hash sulla password ha un grande vantaggio: se il traffico viene registrato o catturato in qualche modo, renderà il lavoro più difficile per quella persona. Inoltre, con http digest, se ssl non è sempre richiesto, puoi consentire agli utenti di scegliere tra http e https. Oppure potresti utilizzare protocolli diversi per server diversi (ad esempio non impongo https per visualizzare / modificare meno importand dati (nome utente, caricamento avatar) ma impongo https sulla fatturazione e su altre parti del sito (in questo modo posso ridurre il carico su alcuni server, se / quando necessario)
vlad b.

3

Se stai cercando di sostituire una password in chiaro su HTTPS con una password con hash su HTTP, stai cercando problemi. HTTPS genera una chiave di transazione condivisa casuale quando si apre un canale di comunicazione. È difficile da decifrare, poiché sei praticamente limitato alla forzatura bruta della chiave condivisa utilizzata per una transazione (relativamente) a breve termine. Mentre il tuo hashish può essere semplicemente annusato, portato fuori linea e guardato in alto in un tavolo arcobaleno o semplicemente forzato per un lungo periodo di tempo.

Tuttavia, un offuscamento della password lato client di base (non hash) inviato tramite HTTPS ha qualche valore. Se non sbaglio questa tecnica è effettivamente utilizzata da alcune banche. Lo scopo di questa tecnica non è proteggere la password dallo sniffing attraverso il cavo. Piuttosto, è per impedire che la password sia utilizzabile per stupidi strumenti di spionaggio e plug-in del browser che catturano ogni richiesta HTTPS GET / POST che vedono. Ho visto un file di registro acquisito da un sito Web dannoso che conteneva 400 MB di transazioni GET / POST casuali acquisite dalle sessioni utente. Puoi immaginare che i siti Web che utilizzavano solo HTTPS vengano visualizzati con password in chiaro nel registro, ma anche i siti Web con un offuscamento molto semplice (ROT13) vengono visualizzati con password che non sono immediatamente utilizzabili.


"ma anche i siti web con un offuscamento molto semplice (ROT13) verrebbero visualizzati con password che non sono immediatamente utilizzabili" - questo contraddice l'affermazione originale. La chiave è che non sono IMMEDIATAMENTE utili, ma è davvero inutile. La password e il suo ROT13 sono equivalenti. MA se SHA2 la password, non sarà presente nei log (in modo che i tuoi amministratori non vengano a conoscenza delle possibili password degli utenti per altri sistemi) e NON sei PIÙ in violazione di quasi tutte le leggi sulla privacy.
Levente Pánczél

2

Se sei connesso a un server https, il flusso di dati tra il server e il browser dovrebbe essere crittografato. I dati sono solo testo normale prima di essere inviati e dopo essere stati ricevuti. Articolo di Wikipedia


I proxy non intercettano questi dati?
Jader Dias

A quanto ho capito lo fanno, ma il proxy non è responsabile della crittografia / decrittografia e, a meno che non sia un proxy senza scrupoli, trasmette solo i dati. Il tipo e la forza della crittografia dipendono da ciò che il server e il client possono supportare.
jac

1
Anche se il proxy è unxrupulous, non può decrittografare i dati poiché vengono crittografati utilizzando la chiave pubblica del server. L'unico modo in cui un proxy può decrittografare i dati è falsificare il certificato del server con una chiave diversa
Kiersten Arnold

@Jader. Se lo facessero, HTTPS renderebbe piuttosto debole. quando ti autentichi a un server con HTTPS, ottieni una garanzia (supponendo che il certificato sia valido) che ti stai connettendo a un determinato server e che hai un percorso crittografato da un'estremità all'altra. Ipoteticamente, un uomo nel mezzo di attacco potrebbe essere fatto per ingannarti, naturalmente, ma non è la stessa cosa di un proxy web di base.
Peter Recore

2

Dichiarazione di non responsabilità: non sono affatto un esperto di sicurezza e sto postando con la speranza che altri critichino la mia posizione come eccessivamente cauta o migliorabile e imparerò da essa. Detto questo, voglio solo sottolineare che l'hashing quando lascia il tuo client non significa che non devi fare l'hash sul back-end prima di inserirlo nel database.

Fai entrambi

Fai entrambe le cose perché:

  1. L'hashing durante il viaggio aiuta a coprire le vulnerabilità del trasporto, se la connessione SSL è compromessa, non possono ancora vedere la password grezza. Non importa in termini di capacità di impersonare utenti autorizzati, ma proteggerà i tuoi utenti dal vedere le loro password lette insieme alla loro email. La maggior parte delle persone non segue le migliori pratiche e utilizza la stessa password per molti dei propri account, quindi questa può essere una grave vulnerabilità per i tuoi visitatori.

  2. Se qualcuno, in qualche modo, è stato in grado di leggere le password dal database (questo accade, pensa SQL injection), non sarà comunque in grado di eseguire azioni privilegiate che impersonano gli utenti tramite la mia API. Ciò è dovuto all'asimmetria hash; anche se conoscono l'hash memorizzato nel tuo DB, non conosceranno la chiave originale usata per crearlo ed è quello che il tuo middleware di autenticazione usa per autenticarsi. Questo è anche il motivo per cui dovresti sempre salare il tuo deposito di hashish.

Certo, potrebbero fare molti altri danni se avessero libero sfogo per leggere ciò che vogliono dal tuo database.

Voglio solo sottolineare qui che se decidi di eseguire l'hashing della chiave prima della partenza dai tuoi clienti, non è sufficiente: l'hashing back-end è, imo, molto più importante ed è per questo: se qualcuno sta intercettando il traffico dal tuo client, quindi vedranno il contenuto del passwordcampo. Che si tratti di un hash o di un testo semplice, non importa: possono copiarlo alla lettera per impersonare un client autorizzato. (A meno che tu non segua i passaggi descritti da @ user3299591 e ti consiglio di farlo). L'hashing della colonna DB, d'altra parte, è una necessità e per nulla difficile da implementare.



0

In realtà sarebbe meno sicuro eseguire l'hash della password e inviarla su un canale non crittografato. Esponerai il tuo algoritmo di hashing sul client. Gli hacker potrebbero semplicemente annusare l'hash della password e quindi usarlo per hackerare in un secondo momento.

Utilizzando HTTPS, impedisci a un hacker di ottenere la password da un'unica fonte, poiché HTTPS utilizza due canali, entrambi crittografati.


1
In realtà lo farei di nuovo nel server e utilizzerei comunque HTTPS, quindi modifica la tua risposta contemplando questo scenario.
Jader Dias

@Jader, il punto è che tutto ciò di cui un attaccante ha bisogno ora è il primo hash, piuttosto che una password. In effetti, l'hash che si prende della password sul lato client è ora altrettanto utile della password stessa. Quindi non stai davvero guadagnando molta sicurezza.
Peter Recore

qualcuno ha mai pensato di non inviare parti del token? come se conoscessi i tuoi metodi di hashing, perché dovresti inviarlo. il server non dovrebbe conoscere la chiave del client da decrittografare?
jemiloii

0

Se c'è un vantaggio e se è più (o meno) sicuro dipende davvero dall'implementazione. C'è probabilmente qualche vantaggio, ma se lo implementi male, potresti sicuramente creare una soluzione meno sicura rispetto al passaggio anche di una password in chiaro.

Questo può essere visto dalla prospettiva di due tipi di attacchi: uno con accesso al traffico di rete e un altro con accesso al database.

Se il tuo aggressore è in grado di intercettare la versione in testo normale del traffico di rete, vedere un hash della password è più sicuro che vedere la password in chiaro. Sebbene l'attaccante possa ancora accedere al tuo server utilizzando quell'hash, richiederebbe un crack a forza bruta (a volte pre-calcolato) di quell'hash per determinare la password che potrebbe essere utile su altri sistemi. Le persone dovrebbero utilizzare password diverse su sistemi diversi, ma spesso non lo fanno.

Se un utente malintenzionato ha ottenuto l'accesso al database, magari tramite una copia di un backup, è necessario assicurarsi che non si possa accedere solo con quella conoscenza. Se, ad esempio, hai memorizzato un hash salato con il nome di accesso come hash(login_name+password)e hai passato lo stesso hash dal client per il confronto diretto, l'attaccante potrebbe scegliere un utente a caso, inviare l'hash letto dal database e accedere come quell'utente senza conoscere la password, aumentando la portata della violazione. In tal caso, l'invio della password in chiaro sarebbe stato più sicuro perché l'aggressore avrebbe avuto bisogno di conoscere il testo in chiaro per poter accedere, anche avendo una copia del database. È qui che l'implementazione è fondamentale. Indipendentemente dal fatto che invii una password in testo normale o un hash lato client di quella password, dovresti eseguire l'hash del valore sul lato server e confrontare tale hash con l'hash memorizzato nel record dell'utente.

Concetti da tenere a mente:

  • Puoi "salare" un hash mescolando un valore unico di ambito al tuo hash, in genere univoco per riga. Il suo scopo è garantire l'unicità degli hash l'uno dall'altro anche se i valori di testo in chiaro che rappresentano sono gli stessi, quindi due utenti con la stessa password avrebbero comunque hash diversi. Non è necessario trattare un sale come un segreto.
  • Durante l'autenticazione, hash sempre sul lato server qualunque valore passi dal client come password (anche se è già hash) e confrontalo con un valore pre-hash memorizzato nel database. Ciò potrebbe richiedere la memorizzazione di una versione con doppio hash della password originale.
  • Quando si crea un hash, considerare l'aggiunta di un salt univoco per server / cluster all'hash, nonché un salt univoco per riga per evitare la corrispondenza con gli hash precalcolati nelle tabelle di ricerca.
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.