Pulizia delle password degli utenti


98

Come devo sfuggire o ripulire le password fornite dagli utenti prima di eseguirne l'hashing e memorizzarle nel mio database?

Quando gli sviluppatori PHP prendono in considerazione l'hashing delle password degli utenti per motivi di sicurezza, spesso tendono a pensare a quelle password come farebbero con qualsiasi altro dato fornito dagli utenti. Questo argomento compare spesso nelle domande PHP relative alla memorizzazione delle password; lo sviluppatore spesso vuole ripulire la password utilizzando funzioni come escape_string()(in varie iterazioni) htmlspecialchars(), addslashes()e altre prima di eseguirne l'hashing e memorizzarla nel database.


1
puoi codificare base64 utente
MSS

No @MSS, non dovresti perché base64 codifica , non crittografa o hashing . Le password dovrebbero sempre essere sottoposte ad hashing .
Jay Blanchard

1
Intendo prima dell'hash;)
MSS

Non dovresti e non devi farlo prima dell'hashing. Dovrai scrivere codice aggiuntivo non necessario @MSS
Jay Blanchard

Risposte:


99

Non dovresti mai scappare, tagliare o utilizzare qualsiasi altro meccanismo di pulizia sulle password che eseguirai l'hashing con PHP password_hash()per una serie di motivi, il più grande dei quali è perché la pulizia aggiuntiva della password richiede codice aggiuntivo non necessario.

Sosterrai (e lo vedi in ogni post in cui i dati dell'utente sono accettati per l'uso nei tuoi sistemi) che dovremmo ripulire tutti gli input degli utenti e faresti bene a ogni altra informazione che accettiamo dai nostri utenti. Le password sono diverse. Le password con hash non possono rappresentare una minaccia di SQL injection perché la stringa viene trasformata in hash prima dell'archiviazione nel database.

L'atto di hashing di una password è l'atto di rendere la password sicura da archiviare nel database. La funzione hash non dà un significato speciale a nessun byte, quindi non è richiesta alcuna pulizia del suo input per motivi di sicurezza

Se segui i mantra di consentire agli utenti di utilizzare le password / frasi che desiderano e non limiti le password , consentendo qualsiasi lunghezza, qualsiasi numero di spazi e qualsiasi carattere speciale hashing renderà la password / passphrase sicura indipendentemente da ciò che è contenuto all'interno la password. A partire da ora l'hash più comune (l'impostazione predefinita), PASSWORD_BCRYPTtrasforma la password in una stringa di 60 caratteri contenente un salt casuale insieme alle informazioni sulla password con hash e un costo (il costo algoritmico di creazione dell'hash):

PASSWORD_BCRYPT viene utilizzato per creare nuovi hash delle password utilizzando l'algoritmo CRYPT_BLOWFISH. Ciò risulterà sempre in un hash utilizzando il formato crypt "$ 2y $", che è sempre largo 60 caratteri.

I requisiti di spazio per l'archiviazione dell'hash sono soggetti a modifiche in quanto vengono aggiunti diversi metodi di hashing alla funzione, quindi è sempre meglio aumentare il tipo di colonna per l'hash archiviato, come VARCHAR(255)o TEXT.

Potresti usare una query SQL completa come password e verrebbe sottoposta ad hashing, rendendola ineseguibile dal motore SQL, ad es.

SELECT * FROM `users`;

Potrebbe essere sottoposto a hashing $2y$10$1tOKcWUWBW5gBka04tGMO.BH7gs/qjAHZsC5wyG0zmI2C.KgaqU5G

Vediamo come i diversi metodi di sanificazione influenzano la password:

La password è I'm a "dessert topping" & a <floor wax>!(Ci sono 5 spazi alla fine della password che non vengono visualizzati qui.)

Quando applichiamo i seguenti metodi di rifilatura otteniamo risultati incredibilmente diversi:

var_dump(trim($_POST['upassword']));
var_dump(htmlentities($_POST['upassword']));
var_dump(htmlspecialchars($_POST['upassword']));
var_dump(addslashes($_POST['upassword']));
var_dump(strip_tags($_POST['upassword']));

Risultati:

string(40) "I'm a "dessert topping" & a <floor wax>!" // spaces at the end are missing
string(65) "I'm a &quot;dessert topping&quot; &amp; a &lt;floor wax&gt;!     " // double quotes, ampersand and braces have been changed
string(65) "I'm a &quot;dessert topping&quot; &amp; a &lt;floor wax&gt;!     " // same here
string(48) "I\'m a \"dessert topping\" & a <floor wax>!     " // escape characters have been added
string(34) "I'm a "dessert topping" & a !     " // looks like we have something missing

Cosa succede quando li inviamo a password_hash()? Vengono tutti sottoposti ad hashing, proprio come la query precedente. Il problema si presenta quando si tenta di verificare la password. Se utilizziamo uno o più di questi metodi, dobbiamo riutilizzarli prima di confrontarli con password_verify(). Quanto segue fallirà:

password_verify($_POST['upassword'], $hashed_password); // where $hashed_password comes from a database query

Dovresti eseguire la password pubblicata attraverso il metodo di pulizia che hai scelto prima di utilizzare il risultato di quella nella verifica della password. È una serie di passaggi non necessari e non migliorerà l'hashish.


Usi una versione PHP inferiore alla 5.5? Puoi usare il password_hash() pacchetto di compatibilità .

Non dovresti davvero usare gli hash delle password MD5 .


13
No. Se ha creato la sua password con spazi finali, che è consentito, deve utilizzarli al login @DanBracuk
Jay Blanchard

12
Come mai @DanBracuk? Se permettiamo all'utente di impostare la password che desidera, inclusi gli spazi iniziali / finali?
Jay Blanchard

16
Ecco perché la maggior parte delle cose richiede di inserire due volte la password scelta. Se l'utente ha aggiunto gli spazi per sbaglio, lo scoprirà prima di andare oltre. Se l'utente lo ha fatto apposta, non è un problema.
Ho lottato con un orso una volta.

4
@MargaretBloom, una regola pratica è solo un'euristica. A volte abbiamo ancora bisogno di riflettere sulle cose, come per le password. Dici "nessuno sa come cambieranno le cose in futuro", ma sembra che se qualcosa cambierà è il modo in cui sfuggiamo ai dati prima di inserirli nel database, nel qual caso gli utenti si troverebbero bloccati quando le loro password no corrispondere più a quello che abbiamo memorizzato. Qual è il pericolo nel non sfuggire agli hash delle password rispetto al pericolo di sfuggirli?
DavidS

3
Esatto: ovviamente "sfuggirai all'hash" nel senso limitato di passarlo correttamente a una query SQL parametrizzata, dove un po 'di codice nel tuo connettore SQL può o non può fare nulla con esso che corrisponda a "escaping", non devi Non lo so e non mi interessa. Semplicemente non dovrai scrivere alcun codice specifico per ottenerlo, perché è completamente routine per tutte le tue query SQL a meno che tu non abbia preso in precedenza alcune decisioni di vita sbagliate.
Steve Jessop

36

Prima di eseguire l'hashing della password, è necessario normalizzarla come descritto nella sezione 4 dell'RFC 7613 . In particolare:

  1. Regola di mappatura aggiuntiva: qualsiasi istanza di spazio non ASCII DEVE essere mappata allo spazio ASCII (U + 0020); uno spazio non ASCII è un qualsiasi punto di codice Unicode avente una categoria generale Unicode di "Z" (ad eccezione di U + 0020).

e:

  1. Regola di normalizzazione: il modulo di normalizzazione Unicode C (NFC) DEVE essere applicato a tutti i caratteri.

Ciò tenta di garantire che se l'utente digita la stessa password ma utilizzando un metodo di immissione diverso, la password deve essere comunque accettata.


3
@DavidS, un luccicante Mac Book nordamericano (che Joe ha usato poco prima di partire) e un computer da Internet café taiwanese scarsamente internazionalizzato (che Joe sta cercando di usare per scaricare è una carta d'imbarco di ritorno).
Margaret Bloom

2
Sembra sciovinista. :-) Grazie comunque.
DavidS

3
Hmm. Se lo fai, dovresti anche convalidare le password per rifiutare quelle che contengono caratteri non ancora assegnati. Sarebbe terribile se un utente usasse NEWFANGLED SPACE, che la tua app non riconosce e quindi hash così com'è, e quindi aggiorni il tuo database di caratteri Unicode e improvvisamente NEWFANGLED SPACE viene mappato su SPAZIO prima dell'hashing, in modo che lui (s) non è più possibile inserire una password che la tua app eseguirà con il vecchio hash.
ruakh

4
@JayBlanchard Perché quando premete una barra spaziatrice su una macchina e quando la premete su un'altra macchina potreste ottenere due differenti punti di codice Unicode, e avranno due differenti codifiche UTF-8, senza che l'utente sia a conoscenza di nulla. Si potrebbe sostenere che questo è un problema che si desidera ignorare, ma RFC 7613 è stato sostenuto da tali problemi di vita reale, non è una raccomandazione di make-work.
Ripristina Monica il

1
@ruakh Una volta deciso di gestire le password in un certo modo, queste devono rimanere gestite in quel modo, altrimenti le cose non funzioneranno per i casi d'uso esistenti. Se si intende modificare il metodo di preelaborazione in futuro, è necessario memorizzarlo lungo la rappresentazione preelaborata e con hash della password. In questo modo, una volta ricevuto l'input, selezioni il metodo di pre-elaborazione / hashing in base a ciò con cui stai confrontando.
Ripristina Monica il
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.