Wie soll ich von Benutzern bereitgestellte Passwörter maskieren oder bereinigen, bevor ich sie hash und in meiner Datenbank speichere?
Wenn PHP-Entwickler erwägen, Passwörter von Benutzern aus Sicherheitsgründen zu hashen, neigen sie oft dazu, an diese Passwörter zu denken, wie an alle anderen vom Benutzer bereitgestellten Daten. Dieses Thema taucht oft in PHP-Fragen zur Passwortspeicherung auf; Der Entwickler möchte das Passwort häufig mit Funktionen wie löschen escape_string()
(in verschiedenen Iterationen), htmlspecialchars()
, addslashes()
und andere, bevor es gehasht und in der Datenbank gespeichert wird.
Sie sollten Passwörter, die Sie mit PHP hashen, niemals entkommen, kürzen oder andere Bereinigungsmechanismen verwenden password_hash()
aus einer Reihe von Gründen, von denen der wichtigste darin besteht, dass eine zusätzliche Bereinigung des Passworts unnötigen zusätzlichen Code erfordert.
Sie werden argumentieren (und Sie sehen es in jedem Beitrag, in dem Benutzerdaten zur Verwendung in Ihren Systemen akzeptiert werden), dass wir alle Benutzereingaben bereinigen sollten, und Sie hätten Recht mit jeder anderen Information, die wir von unseren Benutzern akzeptieren. Passwörter sind anders. Hash-Passwörter können keine Bedrohung durch SQL-Injection darstellen, da die Zeichenfolge vor dem Speichern in der Datenbank in einen Hash umgewandelt wird.
Beim Hashen eines Passworts wird das Passwort sicher in Ihrer Datenbank gespeichert. Die Hash-Funktion gibt keinem Byte eine besondere Bedeutung, daher ist aus Sicherheitsgründen keine Bereinigung ihrer Eingabe erforderlich
Wenn Sie den Mantras folgen, Benutzern die Verwendung von Passwörter / Phrasen sie begehren und dich Passwörter nicht einschränken, das Zulassen einer beliebigen Länge, einer beliebigen Anzahl von Leerzeichen und eines Sonderzeichen-Hashings macht das Passwort / die Passphrase sicher, unabhängig davon, was im Passwort enthalten ist. Ab sofort ist der gebräuchlichste Hash (der Standard), PASSWORD_BCRYPT
wandelt das Passwort in eine 60 Zeichen breite Zeichenfolge um, die ein zufälliges Salz zusammen mit den gehashten Passwortinformationen und Kosten (die algorithmischen Kosten für die Erstellung des Hashs) enthält:
PASSWORD_BCRYPT wird verwendet, um neue Passwort-Hashes mit dem CRYPT_BLOWFISH-Algorithmus zu erstellen. Dies führt immer zu einem Hash im Kryptformat “$2y$”, das immer 60 Zeichen breit ist.
Die Platzanforderungen zum Speichern des Hashs können sich ändern, wenn der Funktion verschiedene Hash-Methoden hinzugefügt werden, daher ist es immer besser, den Spaltentyp für den gespeicherten Hash zu vergrößern, z VARCHAR(255)
oder TEXT
.
Sie könnten eine vollständige SQL-Abfrage als Ihr Passwort verwenden und es würde gehasht, wodurch es von der SQL-Engine nicht ausführbar wird, z.
SELECT * FROM `users`;
Könnte gehasht werden $2y$10$1tOKcWUWBW5gBka04tGMO.BH7gs/qjAHZsC5wyG0zmI2C.KgaqU5G
Mal sehen, wie sich verschiedene Bereinigungsmethoden auf das Passwort auswirken –
Das Passwort ist I'm a "dessert topping" & a <floor wax>!
(Am Ende des Passworts befinden sich 5 Leerzeichen, die hier nicht angezeigt werden.)
Wenn wir die folgenden Trimmmethoden anwenden, erhalten wir einige sehr unterschiedliche Ergebnisse:
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']));
Ergebnisse:
string(40) "I'm a "dessert topping" & a <floor wax>!" // spaces at the end are missing
string(65) "I'm a "dessert topping" & a <floor wax>! " // double quotes, ampersand and braces have been changed
string(65) "I'm a "dessert topping" & a <floor wax>! " // 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
Was passiert, wenn wir diese an senden password_hash()
? Sie werden alle gehasht, genau wie die Abfrage oben. Das Problem tritt auf, wenn Sie versuchen, das Kennwort zu überprüfen. Wenn wir eine oder mehrere dieser Methoden anwenden, müssen wir sie erneut anwenden, bevor wir sie mit vergleichen password_verify()
. Folgendes würde fehlschlagen:
password_verify($_POST['upassword'], $hashed_password); // where $hashed_password comes from a database query
Sie müssten das gepostete Passwort durch die von Ihnen gewählte Bereinigungsmethode laufen lassen, bevor Sie das Ergebnis davon bei der Passwortüberprüfung verwenden. Es ist eine unnötige Reihe von Schritten und wird das Hash nicht besser machen.
Verwenden Sie eine PHP-Version unter 5.5? Du kannst den … benutzen password_hash()
Kompatibilitätspaket.
Sollte man wirklich nicht verwenden MD5-Passwort-Hashes.
Bevor Sie das Passwort hashen, sollten Sie es wie in beschrieben normalisieren Abschnitt 4 von RFC 7613. Bestimmtes:
- Zusätzliche Zuordnungsregel: Alle Instanzen von Nicht-ASCII-Leerzeichen MÜSSEN ASCII-Leerzeichen (U+0020) zugeordnet werden; Ein Nicht-ASCII-Leerzeichen ist jeder Unicode-Codepunkt mit einer allgemeinen Unicode-Kategorie von “Zs” (mit Ausnahme von U + 0020).
und:
- Normalisierungsregel: Unicode Normalization Form C (NFC) MUSS auf alle Zeichen angewendet werden.
Dadurch wird versucht sicherzustellen, dass das Passwort trotzdem akzeptiert wird, wenn der Benutzer dasselbe Passwort eingibt, aber eine andere Eingabemethode verwendet.
Sie können base64-Codierung verwenden
– FRAUEN
7. November 2017 um 5:01 Uhr
Nein @MSS, sollten Sie nicht, weil base64 ist Codierungnicht verschlüsseln oder hashen. Passwörter sollten immer sein gehasht.
– Jay Blanchard
7. November 2017 um 12:33 Uhr
Ich meine vor Haschisch 😉
– FRAUEN
8. November 2017 um 6:01 Uhr
Das sollten und müssen Sie vor dem Hashing nicht tun. Es wird dazu führen, dass Sie unnötigen zusätzlichen Code @MSS schreiben müssen
– Jay Blanchard
8. November 2017 um 13:12 Uhr