È una cattiva idea aggiungere caratteri casuali a ID utente e password?

15

Ho sentito persone dire ancora e ancora che non dovresti implementare il tuo algoritmo di sicurezza, e vorrei chiederti se sto infrangendo questa regola.

Sto creando un'applicazione client-server tradizionale con una svolta: voglio crittografare tutti i dati sul client in modo che anche un utente malintenzionato che ottiene il controllo completo sul mio server non sia in grado di accedere ai dati degli utenti. Cioè, voglio una crittografia end-to-end per la mia applicazione client-server.

Il client crittografa i dati dell'utente con una chiave crittografica derivata dalla password dell'utente, quindi è importante che il server non sia in grado di capire la password perché ciò consentirebbe al server di decrittografare i dati dell'utente. Il client utilizza quindi il protocollo Secure Remote Password per evitare di inviare la password al server. Fin qui tutto bene.

Ora qui è dove il mio design diventa un po 'non ortodosso. Il problema è che gli utenti in generale sono molto cattivi nella creazione di password, in genere selezionando una password dall'elenco delle 10.000 password più importanti, il che renderebbe piuttosto facile per un utente malintenzionato che ha accesso al server di decrittografare i dati dell'utente. Pertanto ho intenzione di generare un insieme casuale di caratteri e aggiungerli al campo ID utente, quindi l'utente dovrebbe accedere con qualcosa di simile a queste credenziali:

User ID: John-CPE4E38J
Password: snoopy

Ma prima di elaborare queste credenziali il codice di login sposta i caratteri casuali nella password in modo che la libreria di autenticazione SRP sottostante veda questo:

User ID: John
Password: snoopy-CPE4E38J

Inoltre, il client offre di ricordare l'ID utente (es. John-CPE4E38J) in modo che la maggior parte delle volte l'utente debba ricordare la propria password.

Cosa ne pensi di questo approccio? Sto violando la regola dell'algoritmo di non-implementazione-proprio-sicurezza? O è un buon modo per rafforzare la sicurezza della mia applicazione?

    
posta Mark 29.01.2015 - 14:53
fonte

3 risposte

7

La tua idea è una specie di trucco. Ma se sei vincolato dal software esistente, che richiede che le credenziali siano costituite da due soli campi, allora potrebbe essere un trucco adeguato.

Se stai scrivendo il codice cliente e non sei sottoposto a vincoli arbitrari, puoi stare meglio usando tre campi separati per fare una chiara distinzione tra lo scopo di ciascuna delle tre stringhe.

Avere l'autenticazione dipende sia da un segreto memorizzato sul computer client che da un segreto ricordato dall'utente è un approccio valido. Questo è un tipo di autenticazione a due fattori, perché l'utente ha bisogno sia della macchina su cui è memorizzato il segreto che della password.

Uno deve preoccuparsi di mantenere un backup del segreto memorizzato sulla macchina. Questo è importante perché se lo perdi, non sarà più possibile decrittografare i dati, quindi tutti i loro dati verranno persi in modo efficace.

Dovresti anche utilizzare una funzione di derivazione della chiave, che richiede del tempo di CPU sul client per ricavare una chiave effettiva dai dati segreti. Se questo richiede 100ms di tempo CPU, è difficilmente percepibile per l'utente, ma avendo bisogno di 100ms di tempo di CPU per ogni tentativo di password rallenterà notevolmente un aggressore. È importante che il tempo della CPU venga speso sul client piuttosto che sul server, perché se si trova sul server, diventa un vettore DoS.

La crittografia di tutti i dati direttamente con una chiave derivata dalla password dell'utente significa che una modifica della password richiederebbe la crittografia di tutti i dati. D'altro canto mantenere una chiave fissa per crittografare i dati e crittografare quella chiave utilizzando la chiave derivata dalla password dell'utente è più efficiente, ma ha una vulnerabilità di sicurezza sottile.

Un utente malintenzionato che ha ricevuto una copia dei dati dal server potrebbe essere in grado di forzare le password di alcuni utenti. Se l'utente malintenzionato ottiene un'altra copia dei dati dal server in un secondo momento, i dati degli utenti possono ancora essere decifrati, anche se l'utente ha scelto una password più strong nel frattempo. Ciò significa che i dati che sono stati crittografati solo dopo che l'utente è passato a una password più strong rimane vulnerabile agli attacchi contro la vecchia password più debole.

Questo problema può essere risolto memorizzando i dati in una struttura ad albero in cui ogni nodo è crittografato con una chiave memorizzata nel nodo padre e la radice viene crittografata utilizzando una chiave derivata dai dati segreti.

Si noti inoltre che i dati segreti memorizzati sul client devono essere modificati ogni volta che cambia la password. Altrimenti non ottieni i benefici di sicurezza previsti.

Si supponga che un utente abbia inizialmente una password debole e che un utente malintenzionato sia in grado di forzare il segreto memorizzato sul client a causa di tale password debole. Se l'utente passa a una password più strong, ma il segreto memorizzato rimane invariato, l'hacker deve solo forzare la nuova password e non la combinazione di password e segreto memorizzato.

    
risposta data 30.01.2015 - 10:27
fonte
29

Sì: stai riscrivendo la sicurezza qui. Esistono già numerose funzioni di derivazione delle password che funzionano, il più noto è PBKDF2 . Usa quello al posto del tuo schema personalizzato.

Quello che stai cercando di fare è, in sostanza, salare la password (con un breve salt) e memorizzare il valore salt nel nome utente. Non è davvero un gran miglioramento.

Qualcos'altro che potresti voler ripensare: con il tuo sistema, la chiave di crittografia è direttamente derivata dalla password dell'utente. Ciò significa che non solo un utente malintenzionato può tentare di decrittografare i dati dell'utente tentando di utilizzare elenchi di password noti (anche se l'utilizzo di una funzione di derivazione della chiave basata su password rende più difficile) ma impedisce anche all'utente di modificare la propria password (altrimenti , è necessario re-crittografare tutti i dati dell'utente).

Senza saperne di più sui tuoi requisiti e sull'ambiente, è difficile suggerire il modo migliore di procedere ma, da quello che descrivi, sono sicuro che ciò può essere notevolmente migliorato. Suggerisco, quindi, di assumere uno specialista per aiutarti a trovare una soluzione adeguata in questo caso.

    
risposta data 29.01.2015 - 15:43
fonte
6

Il tuo approccio è molto simile al concetto di salt in crittografia. Prima di parlare di cosa è un sale, presumo che tu stia almeno memorizzando l'hash delle password degli utenti e non le password in testo semplice. Altrimenti, la tua soluzione è completamente inutile.

Un salt è semplicemente un dato casuale che viene utilizzato quando si esegue l'hashing di una password, ad esempio per scopi di archiviazione. La tua stringa casuale aggiunta al nome utente è effettivamente salata. Quindi, se stavi semplicemente memorizzando gli hash non salati delle password degli utenti, allora, in un certo senso, stai rafforzando in qualche modo la sicurezza della tua applicazione, poiché almeno l'elenco degli hash delle password non sarebbe vulnerabile agli attacchi del dizionario, in linea di principio. Ma solo in quel caso. Ad ogni modo, esistono metodi standard per proteggere gli elenchi degli hash delle password, che non comportano la divulgazione del sale durante l'autenticazione.

Tuttavia, se la tua intenzione era di rendere difficile l'identificazione della password, non fornisce alcuna sicurezza aggiuntiva, poiché la stringa casuale viene fornita all'autore dell'attacco durante l'autenticazione.

    
risposta data 29.01.2015 - 15:51
fonte

Leggi altre domande sui tag