Der ultimative Passwort Hashing Guide in 2017 | Kussin

Der ultimative Passwort Hashing Guide in 2017


19.06.2017 | Benjamin Bortels | Security

Dieser Beitrag orientiert sich an dem Beispiel, dass dem Nutzer ein Registrier und Login Bereich geboten werden müssen. Die Daten werden mit einer Datenbank synchronisiert.

First Things First

Die naive Methode: Klartext

Die einfachste Metode ist – einfach das Passwort in der Datenbank zu speichern – genau so wie es beim Registrieren angegeben wurde – als Plain Text. Dies hat einige Vorteile: Wenn ein Nutzer sein Passwort vergisst, kannst du es einfach in der Datenbank nachschauen lassen und dem Nutzer zusenden. Das Verifizieren des Passworts auf Gleichheit z.b beim Login ist so auch ziemlich einfach. Es wird einfach als Plain Text verglichen. Wenn es übereinstimmt mit der Datenbank wird der Nutzer eingeloggt.
Nun – das ist die naive Angehensweise und offensichtlich eine katastrophale Idee. Und es gibt noch immer Websites von großen Firmen die so ein Verfahren verwenden. Und man kann es sogar beweisen. Sie senden dir einfach dein Passwort als klaren Text zu, wenn du danach bittest.
Ich erzähle dir warum das ein furchtbares Software Design ist. Wenn ein Insider oder Hacker in deine Datenbank gelangt, kann er einfach die Passwörter auslesen. Sie stehen da ja schließlich als Plain Text. Und wenn wir mal ehrlich sind – die meisten Nutzer benutzern ihre Passwörter auf mehreren Seiten. Das macht die Relevanz dieses Themas nur noch deutlicher.
Du denkst dir vielleicht das passiert mir bestimmt nicht. Doch so etwas passiert öfter als du denkst. Frei nach dem Motto „Gelegenheit macht Diebe“. Schließlich wenn wir mal bedenken, dass wenn du so eine Sicherheitslücke hast, sich noch Mehrere in deiner Software verstecken werden.

Die weniger naive aber noch immer unsichere Methode: Verschlüsselung

Wir nehmen das Passwort und verschlüsseln es. Wir verstecken es sozusagen. Eine Verschlüsselung ist immer 2-Way. Wir haben immer einen Key, mit dem wir Daten ver- und entschlüsseln können. Nun – das ist etwas weniger unsicher. Wenn jemand die Datenbank ausliest, sieht er nur die verschlüsselten Passwörter. Dennoch gibt es große Nachteile. Sobald der Key für den Angreifer verfügbar ist, ist das ganze Verfahren nichtig. Ein Insider oder Hacker könnte leicht an Diesen kommen. Das größte Sicherheitsrisiko ist, dass mehre Leute die selben Passwörter nehmen werden. Und wenn wir eine große Anzahl an Nutzern haben, ist es wahrscheinlich, dass dies passieren wird. Selbst wenn wir nicht den Key auslesen können, so können wir dennoch feststellen, ob mehrere Personen das gleiche Passwort haben.

Die noch weniger naive aber nicht weniger dumme Methode: Hashing

Ein Hash ist eine Zusammenfassung von Daten. Es ist ein One-Way Verfahren, bei dem eine unbegrenze Anzahl an Daten zu einem begrenzt langem Text verarbeitet werden. Populäre Hashing Algorithmen sind md5, sha1, sha256 usw. In unserem Falle würden wir also das Passwort beim Registrieren hashen und speichern – und beim Login die Usereingabe wieder hashen und abgleichen. Dieses Verfahren lässt uns wieder bei dem selben Problem wie bei Verschlüsselung enden. Mehre User hätten den gleichen Hash. Was noch viel schlimmer ist, ist die Problematik, dass Hash Algorythmen „geknackt“ werden können – von Google. Nehmen wir mal als Beispiel md5. Md5 wurde 1991 entwickelt und generiert eine 128-Bit-Zeichenkette. 128 Bit entsprechen 16 Bytes was wiederum 32 hex Zeichen entspricht. Eine 32 lange Zeichenkette also. Würden wir beim Registrieren das lächerliche Passwort „passwort1“ verwenden, bekommen wir den MD5 Wert: „64397c8527190222aa6d61b3c23f8e84“. Dieser Wert würde in unserer Datenbank landen. Wenn wir diesen jetzt einfach mal googeln erhalte ich als ersten Treffer diese Seite: https://md5.gromweb.com/?md5=64397c8527190222aa6d61b3c23f8e84. Diese teilt mir mit, dass mein Hash erfolgreich „reversed“ wurde mit dem Ergebnis „passwort1“. Das war jetzt milde gesagt ein sehr Sicherheitsrisiko freundliches Szenario. Aber probiere einfach mal selbst herum. Du wirst merken, dass obwohl Hashing als One-Way gilt, viele Hashes bereits erfolgreich zurückgesetzt wurden.

Die beste Methode: Key-stretching Algorithmen

Normale Hash Funktionen wie sha-1 oder sha-2 sind optimiert auf Effizenz. Sie sind relativ schnell, da sie z.b auch große Dateien verifizieren sollen. Um sich besser vor Brute Force Attacken zu schützen, bei der Millionen von Hashes erstellt und abgeglichen werden, wurden spezielle Hash Algorithmen gebaut. Die Idee dahinter ist, das Hashen zu verlangsamen. Trotzdem ist die Generierung nicht bedeutend langsamer, so dass es auffallen würde.
Solche Verfahren inkludieren in der Regel auch einen Salt, der bei dem Hashen verwendet wird. Auf diese Weise ist es nicht mehr möglich, dass mehrere Nutzer den gleichen Passwort Hash generieren. Die momentanen Standards sind:

  • Argon2
  • bcrypt
  • scrypt

Der momentane PHP Standard (7.1) ist bcrypt . Ein Beispiel für unser Passwort:
„passwort1“ in bcrypt entspricht in meinem ersten Test mit 10 als cost Faktor: „$2a$10$XyBYk3C1RVkrCCu.YQJW8.LmHbcWltWD6X.X3eU7UHUMUjN5hLD.S“
In einem zweiten Test ergibt das selbe Passwort: „$2a$10$KuXMVPh/yWETxlRoBkTTfO1mroGEVZ4TXPJZz1TzKqR4BkKmDknBW“ – Also etwas komplett anderes. Das ist der Vorteil am Salt. Wenn mehrere Nutzer jetzt dieses Passwort hätten, würde man trotzdem nicht deren Gleichheit über den Hash Wert bestätigen können.

Taking bcrypt to the next level

Kombinieren wir jetzt diesen Passwort Hashing Algorithmus mit Verschlüsselung, bekommen wir einen extra Layer von Sicherheit. Der vermeindliche Hacker muss nun erstmal die gehashten Passwörter entschlüsseln, um überhaupt an die Hashes zu kommen. Eine Implementierung dieses Konzeptes in PHP ist hier zu finden: https://github.com/paragonie/password_lock

Zusammenfassung

Wie du siehst ist Passwort Hashing viel mehr als nur Passwörter mit SHA-256 zu hashen.
Korrektes Passwort Hashing ist nicht schwer aber es dennoch zu umgehen ist immer die beste Lösung. Es gibt die Option, das gesamte Verfahren an einen Drittanbieter wie Google oder Facebook weiterzuleiten. Wenn du es dennoch selbst machen musst, halte dich an die Regeln und benutze einen Key-stretching Algorithmus. Versuche nicht einen eigenen Algorithmus zu erstellen. Das geht in der Regel immer schief und macht die ganze Sache angreifbar.