Dieser Absatz erklärt, warum Hash Funktionen zur sicheren Passwortspeicherung benutzt werden, und wie dies am effektivsten bewerkstelligt werden kann.
Warum sollten von Benutzern eingebene Passwörter gehasht werden?
Das Hashing von Passwörtern ist eine der grundlegendsten Sicherheitsüberlegungen, die beim Design aller Anwendungen oder Dienste, die Passwörter von Benutzern akzeptieren, angestellt werden muss. Ohne Hashing können im Falle eines erfolgreichen Angriffs auf den Datenspeicher alle gespeicherten Passwörter gestohlen und sofort verwendet werden, um nicht nur die Anwendung oder den Dienst zu kompromittieren, sondern auch die Konten von Benutzern bei anderen Diensten, wenn diese keine eindeutigen Passwörter verwenden.
Wenn Benutzer-Passwörter vor dem Abspeichern in der Datenbank gehasht werden, wird es für einen Angreifer sehr schwer, das Originalpasswort herauszufinden, während es gleichzeitig immer noch möglich ist, den resultierenden Hash mit dem Originalpasswort zu vergleichen.
Es ist jedoch wichtig zu beachten, dass das Hashing von Passwörtern nur davor schützt, dass sie im Datenspeicher kompromittiert werden, aber nicht unbedingt davor, dass sie durch bösartigen Code, der in die Anwendung oder den Dienst selbst eingeschleust wird, abgefangen werden können.
Warum sind verbreitete Hashfunktionen wie md5() und sha1() nicht für die Speicherung von Passwörtern geeignet?
Hash-Algorithmen wie MD5, SHA1 und SHA256 sind auf Geschwindigkeit und
Effizienz optimiert. Mit modernen Techniken und leistungsstarker Hardware
ist es aber trivial geworden, diese Hash-Algorithmen mit
Brute-Force
-Attacken anzugreifen.
Aufgrund der Geschwindigkeit, mit der ein moderner Computer diese
Hash-Algorithmen umkehren
kann, raten viele
Sicherheitsexperten dringend davon ab, sie zum Hashing von Passwörtern zu
verwenden.
Wie sollten Passwörter gehasht werden, wenn die üblichen Hashfunktionen nicht geeignet sind?
Wenn es um das Hashen von Passwörtern geht müssen zwei wichtige Dinge bedacht werden: Der Berechnungsaufwand und das Salt. Wenn es länger dauert einen Hash zu berechnen, wird ein Brute Force Angriff stark verzögert.
PHP bietet eine native Passworthashing-API die sich auf eine sichere Art um das Hashen und Verifizieren von Passwörtern kümmert.
Der empfohlene Algorithmus für das Hashen von Passwörtern ist Blowfish, welcher auf als Standardalgorithmus von der Passwort Hashing API benutzt wird, da dieser einen signifikant höheren Berechnungsaufwand als MD5 oder SHA1 voraussetzt und trotzdem weiterhin skalierbar ist.
Die Funktion crypt() ist auch für das Hashing von Passwörtern verfügbar, wird aber nur für die Interoperabilität mit anderen Systemen empfohlen. Stattdessen wird dringend empfohlen, wann immer möglich die native Passwort-Hashing-API zu verwenden.
Was ist ein Salt?
Ein kryptografisches Salt sind Daten, die während des Hashens an das Passwort angefügt werden um die Möglichkeit des Angriffs über Rainbowtables zu erschweren. Rainbowtables sind bereits vorberechnete Paare (Schlüssel, Hash), die benutzt werden können, um für einen gegebenen Hash das vorberechnete Passwort nachzuschlagen.
Vereinfacht ausgedrückt ist ein Salt ein zusätzliches Datenelement, das das Knacken von Hashes erheblich erschwert. Es gibt Onlinedienste bei denen man für einen gegebenen Hash das dazugehörige Passwort herausfinden kann. Die Benutzung eines Salts macht es unpraktisch bis unmöglich das Passwort durch die Benutzung dieser Dienste zu finden.
Die Funktion password_hash() generiert ein zufälliges Salt, sollte beim Aufruf der Funktion keines übergeben werden. Dies ist generell der einfachste und sicherste Ansatz.
Wie werden Salts gespeichert?
Die Funktionen password_hash() oder crypt() geben den Salt als einen Teil des generierten Hashs zurück. Dieser Wert sollte unverändert abgespeichert werden, da er Informationen über den Hashalgorithmus enthält und direkt an die Funktion password_verify() übergeben werden kann um ein Passwort zu verifzieren.
Um Timing-Angriffe zu vermeiden, sollte immer password_verify() verwendet werden, anstatt das Ergebnis erneut zu hashen und mit einem gespeicherten Hash zu vergleichen.
Das folgende Diagramm zeigt das Format eines Rückgabewertes der Funktionen crypt() oder password_hash(). Wie zu sehen ist, enthalten die Hashes alle Informationen über den Algorithmus und das Salt, die für die spätere Verifikation von Passwörtern benötigt werden.