Bereinigen von Benutzerkennwörtern

98

Wie kann ich vom Benutzer bereitgestellte Kennwörter maskieren oder bereinigen, bevor ich sie hashe und in meiner Datenbank speichere?

Wenn PHP-Entwickler aus Sicherheitsgründen das Hashing von Benutzerpasswörtern in Betracht ziehen, denken sie häufig an diese Passwörter wie an andere vom Benutzer bereitgestellte Daten. Dieses Thema taucht häufig in PHP-Fragen zur Kennwortspeicherung auf. der Entwickler oft will das Passwort mit Funktionen wie reinigen escape_string()(in verschiedenen Iterationen) htmlspecialchars(), addslashes()und andere , bevor es Hashing und sie in der Datenbank zu speichern.

Jay Blanchard
quelle
1
Sie können Benutzer base64 codieren
MSS
Nein @MSS, sollten Sie nicht, weil base64 codiert , nicht verschlüsselt oder hascht . Passwörter sollten immer gehasht werden .
Jay Blanchard
1
Ich meine vor dem Hash;)
MSS
Das sollten und müssen Sie vor dem Hashing nicht tun. Es wird dazu führen, dass Sie unnötigen zusätzlichen Code @MSS
Jay Blanchard

Antworten:

99

Sie sollten Passwörter, die Sie mit PHPs verwenden, password_hash()aus einer Reihe von Gründen niemals entkommen, kürzen oder einen anderen Bereinigungsmechanismus verwenden. Der größte Grund dafür ist, dass für eine zusätzliche Bereinigung des Passworts unnötiger zusätzlicher Code erforderlich ist.

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 wären für jede andere Information, die wir von unseren Benutzern akzeptieren, richtig. Passwörter sind unterschiedlich. Hashed-Passwörter können keine SQL-Injection-Bedrohung darstellen, da die Zeichenfolge vor dem Speichern in der Datenbank in Hash umgewandelt wird.

Durch das Hashing eines Kennworts wird sichergestellt, dass das Kennwort sicher in Ihrer Datenbank gespeichert wird. Die Hash-Funktion gibt Bytes keine besondere Bedeutung, daher ist aus Sicherheitsgründen keine Bereinigung ihrer Eingabe erforderlich

Wenn Sie den Mantras folgen, Benutzern zu erlauben, die gewünschten Passwörter / Phrasen zu verwenden , und Sie Passwörter nicht einschränken , indem Sie eine beliebige Länge, eine beliebige Anzahl von Leerzeichen und ein Hashing von Sonderzeichen zulassen, wird das Passwort / die Passphrase sicher, unabhängig davon, was darin enthalten ist das Passwort. Ab dem derzeit häufigsten Hash (Standardeinstellung) wird PASSWORD_BCRYPTdas Kennwort in eine 60 Zeichen breite Zeichenfolge umgewandelt, die ein zufälliges Salt zusammen mit den Informationen zum Hash-Kennwort und den Kosten (den algorithmischen Kosten für die Erstellung des Hashs) enthält:

Mit PASSWORD_BCRYPT werden neue Kennwort-Hashes mithilfe des CRYPT_BLOWFISH-Algorithmus erstellt. Dies führt immer zu einem Hash im Krypta-Format "$ 2y $", das immer 60 Zeichen breit ist.

Der Platzbedarf zum Speichern des Hashs kann sich ändern, da der Funktion verschiedene Hashing-Methoden hinzugefügt werden. Daher ist es immer besser, den Spaltentyp für den gespeicherten Hash wie VARCHAR(255)oder zu vergrößern TEXT.

Sie können eine vollständige SQL-Abfrage als Kennwort verwenden, die gehasht wird und von der SQL-Engine nicht ausgeführt werden kann, z.

SELECT * FROM `users`;

Könnte gehasht werden $2y$10$1tOKcWUWBW5gBka04tGMO.BH7gs/qjAHZsC5wyG0zmI2C.KgaqU5G

Mal sehen, wie sich verschiedene Desinfektionsmethoden auf das Passwort auswirken -

Das Passwort lautet 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 wild 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 &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

Was passiert, wenn wir diese senden password_hash()? Sie werden alle gehasht, genau wie bei der obigen Abfrage. 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 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 veröffentlichte Kennwort über die von Ihnen gewählte Bereinigungsmethode ausführen, bevor Sie das Ergebnis bei der Kennwortüberprüfung verwenden können. Es ist eine unnötige Reihe von Schritten und wird den Hash nicht besser machen.


Verwenden Sie eine PHP-Version unter 5.5? Sie können das password_hash() Kompatibilitätspaket verwenden .

Sie sollten wirklich keine MD5-Passwort-Hashes verwenden .

Jay Blanchard
quelle
13
Nein. Wenn er sein Passwort mit nachgestellten Leerzeichen erstellt hat, was zulässig ist, muss er diese beim Login @DanBracuk
Jay Blanchard am
12
Wie so @DanBracuk? Wenn wir dem Benutzer erlauben, das gewünschte Passwort einzurichten, einschließlich führender / nachfolgender Leerzeichen?
Jay Blanchard
16
Aus diesem Grund müssen Sie bei den meisten Dingen Ihr ausgewähltes Passwort zweimal eingeben. Wenn der Benutzer die Leerzeichen bei einem Unfall hinzugefügt hat, wird er dies herausfinden, bevor er fortfährt. Wenn der Benutzer dies absichtlich getan hat, ist dies kein Problem.
Ich habe einmal mit einem Bären gerungen.
4
@MargaretBloom, eine Faustregel ist nur eine Heuristik. Manchmal müssen wir uns noch Gedanken machen, etwa über Passwörter. Sie sagen, "niemand weiß, wie sich die Dinge in Zukunft ändern werden", aber es scheint, dass sich Daten ändern, bevor wir sie in die Datenbank stellen. In diesem Fall werden Benutzer gesperrt, wenn ihre Kennwörter nicht angezeigt werden passen länger zu dem, was wir gespeichert haben. Was ist die Gefahr, Passwort-Hashes nicht zu entkommen, oder die Gefahr, ihnen zu entkommen?
DavidS
3
Genau: Sie werden natürlich "dem Hash entkommen" in dem begrenzten Sinne, dass Sie ihn korrekt an eine parametrisierte SQL-Abfrage übergeben, bei der Code in Ihrem SQL-Connector möglicherweise nichts damit zu tun hat oder nicht, was "Escape" entspricht. Ich weiß es nicht und es ist mir egal. Sie müssen einfach keinen bestimmten Code schreiben, um dies zu erreichen, da dies für alle Ihre SQL-Abfragen völlig routinemäßig ist, es sei denn, Sie haben zuvor einige schlechte Lebensentscheidungen getroffen.
Steve Jessop
36

Bevor Sie das Kennwort hashen, sollten Sie es wie in Abschnitt 4 von RFC 7613 beschrieben normalisieren . Bestimmtes:

  1. Zusätzliche Zuordnungsregel: Alle Instanzen von Nicht-ASCII-Speicherplatz MÜSSEN dem ASCII-Speicherplatz (U + 0020) zugeordnet werden. Ein Nicht-ASCII-Raum ist ein beliebiger Unicode-Codepunkt mit einer allgemeinen Unicode-Kategorie von "Zs" (mit Ausnahme von U + 0020).

und:

  1. Normalisierungsregel: Das Unicode-Normalisierungsformular C (NFC) MUSS auf alle Zeichen angewendet werden.

Dadurch wird sichergestellt, dass das Kennwort weiterhin akzeptiert wird, wenn der Benutzer dasselbe Kennwort eingibt, jedoch eine andere Eingabemethode verwendet.

Legoscia
quelle
3
@DavidS, Ein super glänzendes nordamerikanisches Mac-Buch (das Joe kurz vor seiner Abreise verwendet hat) und ein schlecht internationalisierter taiwanesischer Internetcafé-Computer (den Joe zum Herunterladen verwendet, ist eine Flight-Back-Boarding-Karte).
Margaret Bloom
2
Klingt jingoistisch. :-) Trotzdem danke.
DavidS
3
Hmm. Wenn Sie dies tun, sollten Sie auch Kennwörter überprüfen, um alle Kennwörter abzulehnen, die noch nicht zugewiesene Zeichen enthalten. Es wäre schrecklich, wenn ein Benutzer NEWFANGLED SPACE verwendet, das Ihre App nicht erkennt und daher unverändert hascht, und dann Ihre Unicode-Zeichendatenbank aktualisiert und NEWFANGLED SPACE plötzlich vor dem Hashing SPACE zugeordnet wird, so dass er kann kein Passwort mehr eingeben, das Ihre App mit dem alten Hash hasht.
Ruakh
4
@JayBlanchard Denn wenn Sie eine Leertaste auf einem Computer und auf einem anderen Computer drücken, erhalten Sie möglicherweise zwei verschiedene Unicode-Codepunkte, die zwei verschiedene UTF-8-Codierungen haben, ohne dass der Benutzer etwas bemerkt. Es könnte argumentiert werden, dass dies ein Problem ist, das Sie ignorieren möchten, aber RFC 7613 wurde aus solchen realen Problemen heraus getragen, es ist keine Empfehlung für die Arbeit.
Stellen Sie Monica am
1
@ruakh Wenn Sie sich für eine bestimmte Behandlung von Kennwörtern entschieden haben, müssen diese weiterhin so behandelt werden, da sonst die Probleme bei vorhandenen Anwendungsfällen auftreten. Wenn Sie die Vorverarbeitungsmethode in Zukunft ändern möchten, sollten Sie sie in der vorverarbeiteten und gehashten Darstellung des Kennworts speichern. Auf diese Weise wählen Sie nach Erhalt der Eingabe die Vorverarbeitungs- / Hashing-Methode basierend auf dem, mit dem Sie vergleichen.
Stellen Sie Monica am