Passworte richtig hashen

TL;DR: Dieser Post setzt auf den vorherigen Post zu Lastpass auf und betrachtet die Fragen, die man sich als IT Betrieb dazu stellen sollte, wie man Passworte – generell Logindaten/Credentials – sicher ablegen kann: Welche Verfahren gibt es, welche sind zeitgemäß, und wie lange würde es heute wohl dauern bis Angreifer, die die komplette Logindatenbank stehlen konnten, die Daten entschlüsseln und für sich nutzbar machen können.

Der letzte Post über den Wechsel von Lasspass zu Bitwarden hat ein Thema gestreift, welches danach auch in Gesprächen unter Kollegen noch einmal vertieft wurde und mich schon früher beschäftigt hat:

Wie legt man als IT Betrieb die Passworte der eigenen Nutzer*innen so in den Systemen ab, dass sie möglichst (lange) sicher sind? Selbst im Falle eines Einbruchs in der Art, wie ihn Lastpass erfahren hat?

Es geht hier also um ein Szenario, bei dem Angreifer die gesamten Passworte bzw. Logincredentials abgreifen können, sei es aus den produktiven Systemen, oder wie bei Lastpass aus Backups. Und dann mit allen ihnen zur Verfügung stehenden Ressourcen versuchen können diese zu entschlüsseln.

Warum den Angreifern überhaupt Stolpersteine in den Weg legen?

Wenn Angreifer schon so tief in die Systeme vorgedrungen sind: Was macht es dann noch für einen Sinn sich Gedanken darüber zu machen, ob Passworte mehr oder weniger einfach zugänglich irgendwo herumliegen? Dafür gibt es mehrere Gründe:

  • In Szenarien wie bei Lastpass, bei denen die Daten aus Backups geholt wurden, sind die Angreifer nicht in die produktive Infrastruktur vorgedrungen (zumindest hofft man das). Gut gesicherte Passworte bringen hier die Angreifer zunächst nicht viel weiter
  • Selbst wenn Angreifer tiefer in die Systeme vorgedrungen sind haben sie vielleicht noch nicht die Zugänge, die sie brauchen um noch größeren Schaden anzurichten. Auch hier schützen nicht einfach zugängliche Passworte davor, dass es Angreifer zu leicht haben
  • Schließlich ist dies auch ein Schutz nach innen: Wenn es auch der IT Abteilung selbst nicht möglich ist Passworte im Klartext zu ermitteln kommt man gar nicht erst in die Versuchung risikoreiche ‚Abkürzungen‘ zu nehmen (‚Moment, ich suche Ihnen gerade Ihr vergessenes Passwort raus‘, ‚Wir können uns doch mal als meyer37 anmelden um zu prüfen, was genau bei dem Kollegen nicht funktioniert, dass machen wir immer so.‘, …)

Die Gründe, warum eine IT Abteilung manchmal gerne Passworte im Klartext hätte – z. B. um schwache Passworte zu finden, oder um sie in neu gegründete Systeme überführen zu können – müssen hier letztlich als nachrangig eingestuft werden.

Verschlüsseln oder hashen

Um Passworte nicht im Klartext abzulegen, aber vielleicht doch die Option zu behalten diesen Klartext verfügbar zu machen, könnte man die Passworte verschlüsseln, z. B. mit einem symmetrischen Verfahren wie AES. Im Fall eines Einbruchs in die eigenen IT Systeme besteht allerdings das Risiko, dass dann auch der oder die Schlüssel mit entwendet werden. Bei so einer Vorgehensweise müsste schon ein durchaus wesentlicher Aufwand betrieben werden um die Verschlüsselung selbst wieder sicher zu machen. So ist es den Angreifern beim Lastpass Hack gelungen die Schlüssel zu dem eigentlich verschlüsselten Backup zu erhalten.

Seit langen ist daher die Ablage von Passworten in Form eines Hashes Standard. Hier wird das Passwort unter Verwendung eines Hashfunktion in ein Format – den Hashwert – überführt, welches sich durch diese Eigenschaften auszeichnet:

  • Aus dem Hashwert lässt sich der Originalwert – hier das Passwort – nur sehr schwer wieder ermitteln, im Idealfall nicht viel schneller als durch Durchprobieren aller möglichen Eingaben
  • Der Hashwert hat immer ein identisches Format z. B. mit der gleiche Länge, unabhängig davon wie der Eingabewert war

Zwei klassische Hashfunktionen sind MD5 und SHA-1. Das sind Beispiele für Hashwerte:

EingabewertMD5 HashSHA-1 Hash
abc900150983cd24fb0d6963f7d28e17f72a9993e364706816aba3e25717850c26c9cd0d89d
Der Hashwert hat immer ein identischen Format wie die gleiche Länge, unabhängig davon wie lang der Eingabewert war78eb98ec466e8b9dfd1ffcac23ccd690b5447826036922409c4f77f50ead0432fb5da892
Beispiele für Hashing

Bei einem Loginvorgang werden dann die von Nutzer*innen eingegebenen Passworte erneut durch die Hashfunktion geschickt und dann dieses Ergebnis mit dem beim Setzen des Passwortes erzeugten Hash verglichen. Bei so einer Vorgehensweise braucht es keine geheimen Schlüssel oder dergleichen, der Hash an sich ist ’sicher‘ genug. Wenn er denn richtig gewählt wird und um das schon vorweg zu nehmen: MD5 und SHA-1 sind heute nicht mehr sicher genug! Aber dazu kommen wir gleich, zuerst noch zwei Kochzutaten:

Den Regenbogen versalzen (und pfeffern)

Die Eigenschaft von Hashfunktionen, für die gleiche Eingabe immer zum gleichen Hashwert zu führen, hat bei der Verwendung zur Passwortsicherung zwei Nachteile

  1. Es ist für einen Angreifer, der eine große Menge von gehashten Passworten erhalten hat, direkt erkennbar welche Nutzer*innen identische Passworte nutzen. Hier kann man also mit einem erfolgreich entschlüsselten Passwort gleich mehrere Konten übernehmen
  2. Die Arbeit des Passwortbrechens kann schon vor dem Angriff geleistet werden, in dem man lange im Voraus für riesige Mengen von möglichen Passworten die Hashwerte berechnet und dann nur noch in einer Tabelle – für die sogar eine besonders effiziente Struktur mit dem Namen Rainbow Table entwickelt wurde – nachsehen, welcher Hashwert zu welchem Passwort gehört

Es gibt aber ein einfaches Mittel um Angreifern zumindest diese Abkürzungen zu vermiesen: Bevor das Passwort in die Hashfunktion gesteckt wird vermischt man es noch mit einem zufälligen Wert, der für jedes Passwort individuell erzeugt wird. Erst die Kombination aus diesem Zufallswert – für den sich der Name Salt eingebürgert hat – und dem Passwort wird in die Hashfunktion gesteckt. In der Passwortverwaltung speichert man dann das Salt zusammen mit dem Hashwert, da es für die Überprüfung eines beim nächsten Login eingegebenen Passworts benötigt wird.

Der Angreifer muss dann die Hashwerte für das jeweilige Salt berechnen und wenn dies groß genug ist lohnt sich kein Rainbow Table, da dieser die Kombinationen von allen Salts – wirklich allen, wenn es ein echter Zufallswert ist – und möglichen bzw. wahrscheinlichen Passworten enthalten müsste. Jedes Passwort muss also einzeln und mit entsprechendem Rechenaufwand ermittelt werden.

Eine weitere Ergänzung kann dann ein Pepper-Wert sein: Dieser funktioniert ähnlich wie das Salt, er ist also ein zufälliger Wert, der mit dem Passwort vermengt wird, er wird aber nicht zusammen mit dem Passworthash abgelegt, sondern zum Beispiel in der Konfiguration des Servers, der die Loginvorgänge abwickelt. Er ist also für alle Passworte identisch.

Wann bringt dies einen Schutz? Wenn ausschließlich die Datenbank mit den hashten (und gesalzenen) Passworten abhanden gekommen ist, aber nicht die Serverkonfiguration mit dem Pepper, dann kann ein Angreifer mit diesen Daten nichts mehr anfangen, da ihm ein entscheidendes Geheimnis fehlt um zu überprüfen, ob er ein Passwort richtig geraten hat.

Falls hingegen die Daten der kompletten IT Landschaft gestohlen wurden ist es nur eine Frage der Komplexität dieser Landschaft, ob es Angreifern gelingt zu verstehen wie das Ganze funktioniert und wo der Pfeffer wächst.

Gutes Hashen, schlechtes Hashen

Es gibt eine große Anzahl von Hashfunktionen und nicht alle sind gleich gut geeignet für die Erzeugung von Passworthashes. Tatsächlich sind die oben genannten Funktionen MD5 und SHA-1 nach heutigem Stand überhaupt nicht mehr geeignet, wie sich später in den Abschätzungen für die Entschlüsselungsdauern zeigen wird.

Warum sind sie nicht geeignet? Dieses Hashes wurden für andere Zwecke entwickelt und zwar zur Prüfung ob Dokumente bzw. Datenpakete unverändert sind. In dem ich ein PDF oder ein Softwarepaket durch so eine Hashfunktion schicke kann ich den erhaltenen Wert zur Prüfung mitgeben, ob das Dokument noch so ist, wie es ursprünglich einmal erzeugt oder verschickt wurde. Alle großen Softwarepakete – hoffe ich jedenfalls – bieten auf ihren Downloadseiten auch die Prüfsummen (Hashwerte) an – die der Hersteller selbst ermittelt hat. Wer es ganz genau nimmt erzeugt diese Prüfsumme nach dem Download auf seinem Rechner dann selbst und vergleicht. Nur wenn die Werte Zeichen für Zeichen übereinstimmen kann man sicher sein, dass die Datei noch so ist, wie sie vom Ersteller einmal produziert wurde.

Bei diesen Nutzungen von Hashfunktionen kommt es auf zwei Dinge an: Es muss sehr schwer sein für eine gegebene Prüfsumme ein anderes – gefälschtes – Dokument zu erzeugen, welches die gleiche Prüfsumme ergibt. Und zweitens: Performance. Diese klassischen Hashverfahren sollen möglich wenig Rechenzeit verbrauchen, damit sie auch bei hohen Durchsatzraten einsetzbar sind.

Performance ist genau das, was wir bei Passworthashes nicht wollen!

Die Möglichkeit eine Hashfunktion schnell auszuführen spielt beim Loginvorgang nur eine begrenzte Rolle, ob unsere Nutzer*innen bei diesem Schritt eine Sekunde warten müssen oder nicht werden sie kaum bemerken bzw. es bei diesem seltenen Vorgang akzeptieren. Für einen Angreifer, der Milliarden von Passworthashes erzeugen muss, macht es hingegen einen riesigen Unterschied, ob ein Hash sich in einer Microsekunde berechnen lässt, oder in einer Millisekunde.

Es gibt dabei die grundlegende Schwierigkeit, dass unsere eigenen Server, die die Logins verarbeiten und den Passworthash dabei erzeugen müssen, nicht so performant sein werden wie die spezialisierte Hardware, die Angreifer ggf. ins Feld führen können. Wir müssen also generell in Kauf nehmen, dass Angreifer in der Lage sein werden viel schneller Hashes zu erzeugen als wir selbst. Die Frage ist nur, wie viel schneller?

Die klassischen, performanten Hashfunktionen wie die SHA-2 Familie lassen sich eigentlich nur auf eine Weise für Passworthashes einsetzen: Durch Erhöhung der Rundenzahl. Damit ist gemeint, dass man den aus dem Passwort (und Salt und Pepper) berechneten Hash erneut in die Hashfunktion steckt. In dem Post zu Lastpass steckt dieser Aspekt in der Frage wie viele Runden im PBKDF2-Verfahren gemacht werden sollten. Hier geht es also ggf. um Millionen von Runden, bei denen der Hashwert immer wieder neu berechnet wird. Für ein produktives Loginsystem sind dabei vermutlich noch viel höhere Werte möglich, da man im Gegensatz zu einem Passwortmanager keine Rücksicht auf ggf. leistungsschwächere Smartphoneprozessoren nehmen muss.

Trotzdem bleibt hier das Grundproblem, dass eine Funktion verwendet wird, die letztlich performant sein soll. Aber es gibt heute Alternativen:

Unperformante Hashfunktionen: Bcyrpt, scrypt und Argon2

Das Design einer Hashfunktion, die eine ’schlechte‘ Performance zeigen soll, hat ihre eigene Komplexität und hier hat es immer neue Entwicklungen gegeben. Diese Funktionen sollen generell solche Eigenschaften haben:

  1. Sie müssen natürlich die gleichen Eigenschaften einer Hashfunktion haben, die zuvor genannt wurden
  2. Es soll auch mit spezialisierter Hardware nicht dramatisch viel einfacher sein diese Funktionen auszuführen als mit Standardhardware
  3. Im Algorithmus sind ‚Stellschrauben‘ vorhanden, die es erlauben den Rechenaufwand und bei neueren Funktionen auch den Speicherbedarf einzustellen. Je nach Verfahren in Abhängigkeit voneinander oder auch nicht
  4. Seitenkanalattacken sollen möglichst schwierig sein. Also Wege, bei denen sich z. B. über die Laufzeit des Algorithmus oder den Stromverbrauch der Hardware Informationen über das verarbeitete Passwort gewinnen lassen

Das sind die heute relevantesten Verfahren in der chronologischen Reihenfolge:

bcrypt

Diese Funktion wurde schon 1999 vorgestellt und verbessert die Passwortsicherheit im Vergleich zu den schnellen Hashes bereits deutlich. Sie verfügt über einen einstellbaren Kostenfaktor, den man an die Leistungsfähigkeit der eigenen Loginserver anpassen kann, um so einen Mittelweg zwischen der Wartezeite für die eigenen Nutzer*innen zu finden und dem Aufwand für Angreifer.

Bcrypt hat aus heutiger Sicht das Ziel nicht vollständig erreicht auch mit spezieller Hardware nicht deutlich schneller ausgeführt werden zu können: Gerade der eher geringe Speicherbedarf ermöglicht eine massive Parallelisierung der Hashwertberechnungen.

scrypt

Diese ca. 10 Jahre nach bcrypt vorgestellte Funktion ist bewusst mit einem ‚hohen‘, nicht reduzierbarem Speicherbedarf konzipiert worden. Dies verhindert den Einsatz von günstiger Hardware für massenhafte Berechnungen deutlich, während die eigenen Server damit normalerweise kein Problem haben.

Es kann sowohl der Rechnenzeit- wie auch der Speicherbedarf eingestellt werden, allerdings nicht unabhängig voneinander. Trotzdem gibt es Untersuchungen, bei denen scrypt in bestimmten Parametersetzungen schlechter – also effizienter ausführbar – abschneidet, als bcrypt. Auch gilt es aus kryptographischer Sicht immer noch als ‚junges‘ Verfahren und löst daher manchmal die Sorge aus, dass es vielleicht noch nicht erkannte Probleme hat.

Argon2

Dieses erstmals in 2014 vorgestellt Verfahren, welches dann noch Weiterentwicklungen erfahren hat, gewann in 2015 die sogn. Password Hashing Competition. Generell ist es damit das aktuellste der drei hier genannten Verfahren, mit den Vor- und Nachteilen, die das mit sich bringt:

Argon2 ist am flexibelsten bei den Einstellungen für Rechenzeit und Speicherbedarf und in Kenntnis der durch spezialisierte Hardware verfügbaren Rechenleistung entwickelt worden. Auf der anderen Seite in kryptographischer Sicht noch jünger und damit potentiell angreifbarer.

In OWASP Password Storage Cheatsheet werden konkrete Empfehlungen für die Parametrisierung dieser Funktionen gegeben.

Wie schnell lassen sich Passworte heute cracken

Es gibt Videos wie dieses, in dem man sich anschauen kann wie man hashcat, ein beliebtes ‚password recovery‘ Tool, einfach an den Start bringt. Aber die Rechenleistung des eigenen Rechners vermittelt einem nur ein ungenügendes Bild davon, was Angreifern potentiell zur Verfügung steht. Interessanter ist da der jährliche Password Table von Hive Systems (nicht zu verwechseln mit der Hive Ransomware Gruppe). Die folgenden Graphiken und Zahlen stammen aus dem Bericht 2022.

Hive Systems hat jeweils ermittelt wie viele Hashes in unterschiedlichen Hashverfahren mit damals verfügbaren Graphikkarten pro Sekunde berechnet werden können und auf dieser Basis geschätzt, wie lange es dauern würde die Hashes für alle denkbaren Passworte einer bestimmten Länge und Zusammensetzung zu berechnen. Und sie haben auch gleich verglichen welche Rechenleistung in der Cloud verfügbar wäre! Es gibt z. B. von Amazon kleine GPU Cluster, die man für überschaubare Kosten mieten kann.

Diese Graphik zeigt die Crackingdauern für Passworte im MD5 Hash mit dem größten damals in der Amazon Cloud verfügbaren Cluster mit 8 GPUs. Während die getestete Graphikkarte auf ca. 70 Milliarden MD5 Hashes pro Sekunde kommt, ist der Cluster in der Cloud in der Lage mehr als 500 Milliarden Hashes zu berechnen. Damit kommt Hive auf diese Tabelle:

Dauer zum Cracken von MD5 gehashten Passworten in der Amazon Cloud. Quelle: Hive Systems

Ein 8 Zeichen langes Passwort – wohlgemerkt jedes 8 Zeichen lange Passwort! – kann also in der Cloud in weniger als einer Stunde errechnet werden. Wenn man bedenkt, dass die meisten von uns keine wirklich zufälligen Passworte verwenden mit Groß- und Kleinschreibung und Zahlen und weiteren Zeichen, wird es meist noch viel schneller gehen. Daher sind auch Passworte mit mindestens 12 Zeichen, wie sie das BSI aktuell empfiehlt, nicht lange sicher, wenn sie als MD5 Hash gespeichert werden.

Der Artikel von Hive vergleicht dabei die in 2022 aktuellen Zahlen mit der vorherigen Auswertung in 2020. Und kann deutliche Rechenleistungssteigerungen zeigen. Ein Passwort, dass heute noch 5 Jahre zur Ermittlung brauchen würde, ist daher in einem Jahr vielleicht schon in der Hälfte der Zeit knackbar.

Und letztlich sind diese Zahlen bzw. die hier eingesetzte Hardware keine Obergrenze: Es gibt spezielle Hardware mit deutlich mehr Leistung und Software wie die von Elcomsoft, die in der Lage ist die Arbeit auf zehntausende von Rechnern zu verteilen.

In den weiteren Auswertungen zeigt sich dann der Vorteil von bcrypt. Diese Graphik basiert auf dem gleichen Hardwareszenario, nur dieses Mal mit bcrypt Hashes:

Dauer zum Cracken von bcrypt gehashten Passworten in der Amazon Cloud. Quelle: Hive Systems

Mit bcrypt ist die Anzahl der Hashes pro Sekunde im Amazon GPU Cluster auf eine Million zurückgefallen. Es geht aus dem Artikel leider nicht hervor, mit welchem Kostenfaktor die Hashes erzeugt wurden. Da die Erhöhung des Kostenfaktors um 1 die Rechenzeit für einen Hash in etwa verdoppelt ist es ein deutlicher Unterschied, ob der Faktor 1 oder 15 war.

In dieser Konstellation müssen Angreiferdeutlich mehr Hardware einsetzen, oder gut darin sein den Suchraum einzugrenzen, um in vernünftiger Zeit zu einem Erfolg zu kommen. Auch wenn bcrypt heute nicht mehr als das modernste Verfahren gilt, ist es weiterhin in der Lage Angriffe auf Passworthashes deutlich zu verlangsamen.

Und trotzdem: Es kommt weiterhin auf die Passwortqualität an

Man sieht an den Auswertungen deutlich, welche Verantwortung als IT Betrieb man bei der sicheren Ablage von Logindaten hat. Aber man sieht auch: Wenn die verwendeten Passworte schlecht sind – zu kurz, zu einfach, in vielen anderen Diensten verwendet – nutzt auch das beste Hashverfahren nichts.

Eine Absicherung der Infrastruktur muss also auf allen Ebenen zugleich erfolgen, damit sie auch in dem hier beschriebenen Szenario wirksam werden kann. Und eine 2-Faktor-Authentifizierung kann helfen den unmittelbaren Schaden eines Verlusts der Passworte zu begrenzen. Sofern die dafür notwendigen Geheimnisse nicht gleich mit gestohlen wurden.

ihbrune

1991-1996: Studium der Naturwissenschaftlichen Informatik an der Universität Bielefeld. Abschluss mit der Diplomarbeit zum Thema 'Analyse von ein- und mehrdimensionalen Zeitreihen mit der Karhunen-Loève- und Wavelet Transformation' || 1996-1997: Wissenschaftlicher Mitarbeiter am Lehrstuhl Prof. A. Knoll in der Technischen Fakultät der Universität Bielefeld im Projekt 'LANeCo: Local Area Net Configuration' || 1998- 2018: Tätigkeit im BIS - Bielefelder Informationssystem an der Universität Bielefeld || Seit Oktober 2018: Leitung der Abteilung Informationssysteme und Prozessunterstützung im BITS