Passwort Hashing - Kryptografische Hashfunktionen
Einleitung
Passwortbasierte Authentifizierung ist die wohl am häufig genutzte Methode, mit der sich ein*e Benutzer*in gegenüber einer anderen Person, einem Gerät, oder einem System authentifizieren kann. Beispiele hierfür sind nicht nur das Anmelden mit einem Passwort bei einem Webdienst wie Twitter, sondern auch die Zahlenkombination eines Fahrradschlosses, das WLAN Passwort im Heimrouter, oder auch eine Kundennummer mit der in der Service Hotline überprüft wird, ob jemand wirklich die Person ist, welche sie vorgibt zu sein. In jedem dieser Fälle muss das Passwort, auch Geheimnis genannt, von dem System überprüft werden, bevor dem Benutzer*in der Zugriff gewährt wird. Das System benötigt daher in irgendeiner Form Wissen um dieses Benutzer-Geheimnis, um überhaupt in der Lage zu sein es überprüfen zu können. Der einfachste Fall einer solchen Überprüfung wäre es, wenn Person A und System B sich auf ein Passwort einigen, welches nur die beiden Parteien kennen. Wenn sich A nun anmelden möchte, dann wird das Passwort an B übermittelt und B prüft mit der eigenen Kopie, ob das übermittelte Passwort mit dem gespeicherten übereinstimmt. Ist dies der Fall, so darf A angemeldet werden, sonst nicht.
Ein integraler Bestandteil ist hierbei, dass das gemeinsame Geheimnis auch wirklich geheim bleibt und nur A und B bekannt ist. Sollte das Geheimnis in die Hände von einer weiteren Partei C fallen, so könnte sich C unbemerkt als A ausgeben und sich auch anmelden. Dies versteht man in der Regel als Passwort Leak und muss unter allen Umständen verhindert werden. Gerade bei Webservices ist es nicht trivial Geheimnisse geheim zu halten. Immer wieder kommt es vor, dass Logindaten von Webservices kompromittiert werden und beispielsweise Datenbanken mit Benutzerdaten im Internet veröffentlicht werden. Solche Leaks sind nicht nur auf kriminelle Aktivitäten zurückzuführen, sondern auch auf mangelnde Sicherung der Betreiber. Die Betreiber sind also dazu verpflichtet Gegenmaßnahmen anzuwenden, so dass ein Angreifer so viele Hürden wie möglich zu überwinden hat, bevor er sich als jemand anderes anmelden kann. Jemand, der sich absichern möchte muss also damit rechnen, dass ein Angreifer unbemerkt Zugriff auf die Passwortdatenbank haben kann. Deswegen dürfen Passwörter nicht im Klartext gespeichert werden. Doch wie kann ein Plattformbetreiber dies realisieren um nach den aktuellen Standards so gut wie möglich gesichert zu sein? Im Folgenden soll dieser Artikel beschreiben welche Sicherheitsbausteine benutzt werden können um Passwörter abzusichern, wie Angreifer vorgehen um dennoch diese Sicherungen zu umgehen, und wie ein Betreiber sich wiederum dagegen zu Wehr setzen kann. Das Mittel der Wahl sind sogenannte kryptografische Hashfunktionen.
Kryptografische Hashfunktionen
Wie eingangs betrachtet sollen Passwörter nicht im Klartext gespeichert werden. Das heißt wir brauchen einen Mechanismus der ein Passwort entgegen nimmt und so transformiert, dass es für einen Angreifer nicht möglich ist, diese Transformation wieder zurück zu rechnen. Das kryptografische Konzept welches hier zu Grunde liegt, sind so genannte One Way Functions. Dies sind mathematische Funktionen und haben als Eingabe z.B. ein Passwort und liefern einen Rückgabewert. One Way Function haben zusätzlich die Eigenschaft, dass sie sehr leicht und schnell für Computer zu berechnen sind, jedoch nicht effizient invertiert werden können. Das bedeutet, dass zu einem gegebenen Rückgabewert von einem Computer in einer gewissen Zeitspanne keine Eingabe, auch Urbild genannt, gefunden werden kann, welches den Rückgabewert als Ergebnis unter der Funktion hat. Das Rückrechnen ist damit praktisch nicht möglich. In der Theorie konnte bis heute nicht formal gezeigt werden konnte, dass diese One Way Functions überhaupt existieren. In der Praxis haben wir jedoch Konstruktionen, die diese Eigenschaft hinreichend gut erfüllt. Dies sind kryptografische Hashfunktionen.
Eine Hashfunktionen ist nichts anderes als eine Funktion welche eine Eingabe beliebiger Länge entgegen nimmt und einen so genannten Message Digest, oder Hashwert berechnet. Dieser Hashwert hat dabei, unabhängig von der Eingabe, eine konstante Länge.
Kryptografische Hashfunktionen haben noch weitere Sicherheitsaspekte. Ein wichtiger Aspekt ist, dass ein Angreifer nicht effizient ein Urbild eines beliebigen Hashwertes berechnen kann (Preimage Resistance). Diese Eigenschaft ist jedoch für eine Sicherheitsanalyse zu stark. Das Ziel ist unter möglichst schwachen Sicherheitsanforderungen an die Hashfunktion eine hinreichende Sicherheit zu gewährleisten, zumal wie oben angemerkt nicht gezeigt werden kann, dass eine Funktion diese Einweg-Eigenschaft besitzt. Daher bedient man sich der Eigenschaft der Kollisionsresistenz. Diese ist schwächer als die Preimage Resistanz, aber hinreichend um sichere Algorithmen und Protokolle zu entwerfen. Eine Kollision bezieht sich hierbei auf die Tatsache, dass es mehr Nachrichten als Hashwerte gibt und dies zwangsläufig dazu führen muss, dass es mehrere Nachrichten gibt, die den gleichen Hashwert haben. Für Passworte bedeutet dies, dass es mehrere unterschiedliche, aber äquivalente Passwörter gibt, die den gleichen Hashwert haben. Die Kollisionsresistenz beschreibt die Eigenschaft, dass es für einen Angreifer nicht effizient möglich sein soll, dass für einen Hashwert zwei Eingaben gefunden werden können, die den gleichen Hashwert abbilden.
Angriffe auf Hashfunktionen
Da es nur endlich viele Hashwerte unter einer Hashfunktion gibt, führt ein naiver Brute Force Ansatz zu einem einfachen, wenn auch aufwendigen, Verfahren um ein Hashwert zurück auf ein Urbild zu führen. Mit Hilfe des Geburtstagsparadoxons lässt sich zeigen, dass für eine Hashfunktion mit Hashwerten der Länge von n Bit ca. 2^(n/2) mögliche Passwörter ausprobiert werden müssen um einen Hashwert mit ca. 50% Wahrscheinlichkeit zu treffen. Daher ist die Länge eines Hashwertes einer der wichtigsten Sicherheitsfaktoren einer Hashfunktion. Es sollten zur Zeit nur noch Hashfunktionen benutzt werden, die eine Hashwert Länge von mindestens 256 Bit haben. Mögliche Kandidaten sind z.B. SHA-256, SHA-3, oder ähnliche.
Hashfunktionen wie MD5 und SHA-1 sollten nicht mehr genutzt werden. Beide haben zum einen eine Hashlänge unter 256 Bit, zum anderen wurden Schwachstellen innerhalb dieser Algorithmen gefunden, welche genutzt werden können um den Suchraum für den Bruteforce Angriff weiter einzuschränken. Dadurch sind noch weniger Versuche notwendig um ein passendes Urbild zu finden.
Zu den aktuellen Hashfunktionen, auch für MD5 oder SHA-1, gibt es aktuelle keine Angriffmethode, die wesentlich besser ist als die Bruteforce Methode. Angreifer nutzen daher hochoptimierte Bruteforce Verfahren um Hashwerte brechen zu können. Ein bekanntes Verfahren sind Rainbow Tables. Hierbei werden auf effiziente Weise Passwörter und Hashwert Paare vorberechnet, damit ein Passwort durch nachschlagen in der Rainbow Table aufgelöst werden kann. Der besondere Ansatz bei Rainbow Tables ist, dass nicht alle Passwort-Hashwerte Paare gespeichert werden müssen, was die Größe der Rainbow Table erheblich reduziert.
Gegenmaßnahmen
Da die Möglichkeiten von Angreifern durch Bruteforce Methoden wie Rainbow Tables beschränkt ist, müssen Plattformbetreiber die Berechnung von Rainbow Tables für Angreifer so aufwändig wie möglich machen. Ohne diese Gegenmaßnahmen, kann ein Angreifer einmal eine Rainbow Table erstellen, und dann die Hashwerte für alle Userpasswörter zurürckrechnen. Um es dem Angreifer möglich schwer zu machen eine universelle Rainbow Table zu berechnen oder gar eine vorgefertigte zu nutzen, können folgende Maßnahmen umgesetzt werden:
Beim Salting wird nicht nur das Passwort pw gehashed, sondern das Passwort zusammen mit einem Zufallswert s. Dieser Zufallswert ist für jeden Benutzer eindeutig. In der Passwort Datenbank wird dann für einen Benutzer der Hash vom Passworm und Salt H(pw||s) und der Salt s selbst gespeichert. Der Ausdruck pw||s bezeichnet hierbei die Zeichenkettenkonkatenation. Da nun der Salt s ein Teil der Hashberechnung ist, kann ein Angreifer keine vorgefertigte Rainbow Table benutzen, sondern muss eine eigene berechnen. Des weiteren muss der Angreifer für jeden möglichen Salt eine Rainbow Table berechnen um alle Hashes invertieren zu können. Bei einem n Bit Salt sind dies 2^n viele Rainbow Tables zu berechnen. Bei modernen Betriebssystemen werden 16 Byte = 2^(128) Bit lange Salts genutzt. Wenn eine Rainbow Table eine Größe von bspw. 2 Gigabyte hat, bräuchte jemand für alle Salts fast 10^(30) Exabytes. Dies ist praktisch unmöglich.
Ähnlich zum Salt wird auch hier ein Zufallswert p genutzt, welcher zusätzlich zur Hashfunktion übergeben wird. Der Unterschied zum Salt liegt hier darin, dass der Pepper nicht in der Passwort Datenbank gespeichert wird, sondern an einem separaten Speicherort, der gegebenenfalls zusätzlich gesichert werden kann. Sollte die Passwort Datenbank, und damit Passworthashes und Salts, kompromittiert werden, dann kann ein Angreifer dennoch keine Rainbow Tables für einzelne Benutzer anlegen, da er das Pepper nicht kennt. Als Pepper eignet sich ein zufälliger Wert, der global für jeden Benutzer genutzt werden kann.
Ein Angreifer muss für die Berechnung einer Rainbow Table die zu Grunde liegende Hashfunktion sehr oft berechnen. Um es dem Angreifer weiter zu erschweren, kann die Hashfunktion mehrfach auf das Passwort angewendet werden. Man spricht vom einem Workfaktor w, wenn für ein Hashwert die Hashfunktion 2^w mal berechnet wird. Hierbei wird die Ausgabe wieder als Eingabe für die nächste Iteration benutzt. Der Workfaktor kann soweit erhöht werden, bis die Verifikation eines Passwort so lange dauert, dass die Timeout Grenze fast erreicht wird. Damit ist die Hashberechnung für den Plattformserver gerade noch schnell genug. Für einen Angreifer, der viele tausend Male Hashes berechnen muss führt dies zu einem sehr großen zeitlichen Overhead.
Diese Gegenmaßnahmen sorgen dafür, dass ein Angreifer sehr viele Resourcen aufwenden muss um eine Rainbow Table zu erstellen und damit Passwörter invertieren zu können. Es gibt jedoch auch die Möglichkeit Passwort Leaks zu erkennen und damit den Blast Radius zu reduzieren. Hierzu können sogenannte Honeywords benutzt werden.
Unter Honeywords versteht man falsche Passworthashes die in die Passwortdatenbank eingepflegt werden. Diese falschen Hashes sind für jemanden, der nur auf die Passwortdatenbank zugreifen kann nicht von dem richtigen Hashes zu unterscheiden. Zusätzlich gibt es eine weitere Datenbank und einen Honeychecker, der prüfen kann, ob gerade ein Passwort genutzt wurde, welches einen falschen Hash erzeugt hat. Der Honeychecker kann dann den Plattformbetreiber alarmieren, dass Daten aus der Passwortdatenbank geleakt sind. Zusammen mit der Verwendung von Salt und Pepper kann ein Angreifer vermutlich nur ein Passwort invertieren. Wenn dieses Passwort zu einem falschen Hash gehört, dann kann der Plattformbetreiber weitere Schritte unternehmen, ohne das bereits ein Passwort kompromittiert wurde.
Maßnahmen gegen Hardwarebeschleunigung: Hashfunktionen für Passworte
In den letzten Jahren, nicht zuletzt durch den Hype von Bitcoin und anderen Cryptowährungen, kam Spezialhardware auf den Markt für die effizientere Berechnung von Hashwerten. Diese Hashberechnungen sind notwendig für das Mining von neuen Bitcoinblöcken. Diese Spezialhardware kann jedoch auch genutzt werden um Rainbow Tables zu erstellen. Aus diesem Grund sind Algorithmen notwendig geworden, die Angreifern keinen Vorteil verschaffen, wenn sie Spezialhardware benutzen.
Um dies zu realisieren, werden sogenannte memory-hard functions benutzt. Solche Funktionen benötigen während der Berechnung verhältnismäßig viel Arbeitsspeicher und sorgt dafür, dass ein Angreifer viele Resourcen investieren muss. Das Ziel solcher memory-hard functions ist, effizient genug für den Plattformbetreiber zu sein, jedoch zu ineffizient, um viele solcher Berechnung (parallelisiert) auszuführen.
Momentan gibt es mindestens vier Algorithmen, welche aktuelle Standards erfüllen um Passwörter sicher speichert zu können:
- Argon2 ist der Gewinner der Passwort Hashing Competition von 2013-2015 und erfüllt alle Kriterien für sicheres Passwort Hashing. Argon2 ist in verschiedenen Varianten verfügbar und optimiert für die x86 Architektur. Der Hashalgorithmus nutzt aktuelle Intel und AMD CPU Funktionen für Speicher und Cache Zugriff. Wenn für ein neues System Argon2 verfügbar ist, sollte es benutzt werden.
- bcrypt ist eine Hashfunktion basierend auf dem Verschlüsselungsalgorithmus blowfish. Er sollte die zweite Wahl sein, wenn Argon2 nicht verfügbar ist, oder keine spezielle Zertifizierungen wie FIPS-140 von der NIST benötigt werden.
- PBKDF2 wird von der NIST empfohlen und ist FIPS-140 zertifiziert. Die Hashfunktion benutzt intern eine weitere Hashfunktion bzw. HMAC. Die Sicherheitsparameter sind von der intern verwendeten Hashfunktion abhängig. Das NIST empfiehlt die Nutzung von HMAC-SHA-256.
- scrypt ist eine der ersten memory-hard functions und ist besonders für ältere Systeme zu empfehlen.
Werden diese Algorithmen zusammen mit den oberen Gegenmaßnahmen verwendet werden ist davon auszugehen, dass die Passwörter nach aktuellen Standards gut geschützt sind. Es ist jedoch immer darauf zu achten, dass täglich neue Schwachstellen in Hashfunktion entdeckt werden können, die es nötig machen, auf eine andere Hashfunktion umzusteigen. Die aktuelle Entwicklung darf nie aus dem Fokus verschwinden.
Ausblick
Es gibt noch weitere Methoden der Authentifikation, die sogar ganz ohne Passwörter auskommen. In diesem Fall muss natürlich kein Passwort gehashed werden, was wiederum einem Angreifer diesen Angriffsvektor nimmt. Zu diesen passwortlosen Verfahren gehören Digitale Signaturen, bei denen sich ein Benutzer mit einem Zertifikat authentifiziert. Ebenso können PAKEs (Password Authenticated Key Exchanges) benutzt werden, bei denen der Austausch eines kryptografischen Schlüssels mit einer Passwort Abfrage gesichert wird. Dieses Passwort darf jedoch nur einmal geprüft werden, welches damit die Sicherheit garantiert. Zuletzt sind noch Zero-Knowledge Proofs zu erwähnen, bei denen ein Benutzer jemandem beweist, dass er im Besitz eines Geheimnisses ist, ohne jegliche Information über das Geheimnis selbst Preis zu geben. Alle diese Methoden werden in der Praxis aktuell jedoch nicht, oder nur sehr selten eingesetzt.