Hashing macht es Angreifern schwerer, gespeicherte Passwörter zu entschlüsseln, wenn es richtig eingesetzt wird. [...]
Was ist Hashing?
Hashing ist ein kryptografischer Prozess, der verwendet werden kann, um die Authentizität und Integrität verschiedener Eingabetypen zu überprüfen. Es wird häufig in Authentifizierungssystemen verwendet, um die Speicherung von Klartextpasswörtern in Datenbanken zu vermeiden, wird aber auch zur Validierung von Dateien, Dokumenten und anderen Datentypen eingesetzt. Die falsche Verwendung von Hashing-Funktionen kann zu schwerwiegenden Datenschutzverletzungen führen, aber es ist noch schlimmer, sensible Daten gar nicht erst mit Hashing zu sichern.
Hashing versus Verschlüsselung
Hashing ist eine einseitige kryptografische Funktion, während Verschlüsselung in beide Richtungen funktioniert. Verschlüsselungsalgorithmen nehmen eine Eingabe und einen geheimen Schlüssel und erzeugen eine zufällig aussehende Ausgabe, die als Chiffriertext bezeichnet wird. Dieser Vorgang ist umkehrbar. Jeder, der den geheimen Schlüssel kennt oder erhält, kann den Chiffriertext entschlüsseln und die ursprüngliche Eingabe lesen.
Hashing-Funktionen sind nicht umkehrbar. Die Ausgabe einer Hash-Funktion ist eine Zeichenkette fixer Länge, die als Hash-Wert, Digest oder einfach als Hash bezeichnet wird. Diese sind nicht unbedingt dazu gedacht, geheim gehalten zu werden, da sie nicht in ihre ursprünglichen Werte zurückgewandelt werden können. Eine wichtige Eigenschaft einer Hash-Funktion ist jedoch, dass eine eindeutige Eingabe beim Hashing immer den gleichen Hash-Wert ergeben muss. Wenn zwei verschiedene Eingaben denselben Hash-Wert haben können, wird dies als Kollision bezeichnet, und je nachdem, wie einfach es rechnerisch ist, eine solche Kollision zu finden, kann die Hash-Funktion aus Sicherheitsgründen als gebrochen betrachtet werden.
Hashing ist bei der Speicherung von Passwörtern in Datenbanken fast immer der Verschlüsselung vorzuziehen, da Angreifer im Falle einer Kompromittierung keinen Zugriff auf die Klartext-Passwörter erhalten und es für die Website keinen Grund gibt, jemals das Klartext-Passwort des Benutzers zu kennen. Wenn Sie jemals die Mitteilungen von verschiedenen Firmen erhalten haben, dass „unsere Vertreter niemals nach Ihrem Passwort fragen werden“, dann ist das ein Teil des Grundes, warum sie es nicht tun: Sie haben keine Verwendung dafür, weil sie Ihr Passwort nicht haben. Sie haben eine nicht umkehrbare kryptographische Repräsentation Ihres Passworts – seinen Hash-Wert.
Das heißt, dass Unternehmen, die Sicherheitsverletzungen erleiden, in ihren öffentlichen Bekanntmachungen oft den Begriff „Verschlüsselung“ missbrauchen und Kunden darauf hinweisen, dass ihre Passwörter sicher sind, weil sie verschlüsselt wurden. Das liegt wahrscheinlich daran, dass das allgemeine Publikum mit der Bedeutung von Hashing nicht sehr vertraut ist, so dass ihre PR-Abteilungen Verwirrung vermeiden wollen. Für außenstehende Beobachter ist es jedoch schwierig, die mit einer Sicherheitsverletzung verbundenen Risiken einzuschätzen, denn wenn die Kennwörter wirklich verschlüsselt waren, dann ist das Risiko höher als wenn sie gehasht wurden und die nächste Frage sollte lauten: Wurde der Chiffrierschlüssel ebenfalls kompromittiert? Fälle, in denen Verschlüsselung anstelle von Hashing für Passwörter verwendet wurde, kommen vor.
Im Jahr 2013 kam es bei Adobe zu einer Sicherheitsverletzung, bei der Informationen von Millionen von Konten gestohlen wurden, darunter auch verschlüsselte Passwörter. Adobe hatte die meisten seiner Systeme auf die Verwendung von Hashing umgestellt, aber bei dem angegriffenen Server handelte es sich um einen Backup-Server, den das Unternehmen außer Betrieb nehmen wollte und auf dem Passwörter gespeichert waren, die mit der Triple DES-Chiffre im ECB-Modus verschlüsselt waren. Während die Angreifer den Entschlüsselungsschlüssel nicht erlangen konnten, ist die Verwendung dieser Chiffre im ECB-Modus dafür bekannt, dass sie Informationen preisgibt, wodurch Brute-Force-Angriffe eine erhebliche Anzahl von Passwörtern wiederherstellen können.
„Verschlüsselung sollte nur in Grenzfällen verwendet werden, in denen es notwendig ist, das ursprüngliche Passwort zu erhalten“, so das Open Web Application Security Project (OWASP) in seinen Empfehlungen zur Passwortspeicherung. „Einige Beispiele dafür, wo dies notwendig sein könnte, sind: Wenn die Anwendung das Passwort zur Authentifizierung gegenüber einem externen Legacy-System verwenden muss, das SSO nicht unterstützt [oder] wenn es notwendig ist, einzelne Zeichen aus dem Passwort abzurufen. Die Möglichkeit, Passwörter zu entschlüsseln, stellt ein ernsthaftes Sicherheitsrisiko dar und sollte daher einer vollständigen Risikobewertung unterzogen werden. Wenn möglich, sollte eine alternative Architektur verwendet werden, um die Notwendigkeit zu vermeiden, Passwörter in verschlüsselter Form zu speichern.“
Wie Hashing bei der Authentifizierung verwendet wird
Wenn Benutzer in Authentifizierungssystemen ein neues Konto erstellen und ihr gewähltes Passwort eingeben, durchläuft der Anwendungscode dieses Passwort durch eine Hashing-Funktion und speichert das Ergebnis in der Datenbank. Wenn sich der Benutzer später authentifizieren möchte, wird der Vorgang wiederholt und das Ergebnis mit dem Wert aus der Datenbank verglichen. Wenn es eine Übereinstimmung gibt, hat der Benutzer das richtige Passwort angegeben.
Wenn der Benutzer sein Passwort vergisst, umfasst der Passwort-Wiederherstellungsprozess die Überprüfung seiner Identität – normalerweise durch den Nachweis des Besitzes der E-Mail, die zum Erstellen eines Kontos verwendet wurde, indem er auf einen eindeutigen Link zum Zurücksetzen des Passworts klickt, der per E-Mail gesendet wird – und ermöglicht dem Benutzer dann, ein neues Passwort und damit einen neuen Passwort-Hash in der Datenbank festzulegen. Wenn der Passwort-Wiederherstellungsprozess dazu führt, dass dem Benutzer sein altes Passwort per E-Mail zugeschickt oder im Browser angezeigt wird, dann ist die Implementierung unsicher und die besten Sicherheitsverfahren wurden nicht eingehalten.
Das heißt, selbst wenn Hashing verwendet wird, können Entwickler Implementierungsfehler machen, z. B. indem sie eine Hashing-Funktion verwenden, die als unsicher bekannt ist und anfällig für Brute-Force-Angriffe ist. Beispiele für solche Hashing-Verfahren, die früher sehr beliebt waren, aber inzwischen veraltet sind, sind MD5 und SHA-1.
MD5 wurde 1991 entwickelt und war lange Zeit die De-facto-Hashing-Funktion, auch nachdem Kryptoanalytiker gezeigt hatten, dass sie theoretisch unsicher ist. Leider wird MD5 auch heute noch häufig in alten Anwendungen oder von Entwicklern verwendet, die von Sicherheit keine Ahnung haben. Der erste Angriff durch partielle Kollisionen wurde 1996 theoretisiert und eine vollständige Kollision wurde 2004 demonstriert. Heute können MD5-Kollisionen innerhalb von Sekunden auf einem normalen Heimcomputer gefunden werden und der Algorithmus ist extrem anfällig für Brute-Force-Angriffe.
SHA-1 (Secure Hash Algorithm 1) wurde 1995 von der NSA entwickelt und war ein empfohlener NIST-Standard. Seit 2005 ist bekannt, dass die Funktion gegen gut finanzierte Angreifer mit Zugang zu Cloud-Rechenleistung unsicher ist. Im Jahr 2017 haben Sicherheitsforscher des Centrum Wiskunde and Informatica (CWI) in den Niederlanden, der Nanyang Technological University (NTU) in Singapur und von Inria in Frankreich in Zusammenarbeit mit Google eine praktische Kollision gegen SHA-1 nachgewiesen, indem sie zwei verschiedene PDF-Dateien mit derselben SHA-1-Signatur erzeugt haben. SHA-1 wurde für TLS-Zertifikate und andere Verwendungszwecke veraltet, wird aber immer noch häufig in älteren Geräten und Systemen für eine Vielzahl von Zwecken verwendet, einschließlich der Validierung von Dateisignaturen in Code-Repositories, Software-Updates und mehr.
Für das Hashing und die Speicherung von Passwörtern empfiehlt ein aktueller IETF-Entwurf die Verwendung von Argon2 (dem Gewinner der 2015 Password Hashing Competition), Bcrypt, Scrypt oder PBKDF2. Zum Hashing gehört jedoch mehr als nur der verwendete Algorithmus. Zum Beispiel ist eine minimale Passwortlänge von acht Zeichen auch wichtig, weil es Brute-Force-Angriffe, die auf Wörterbuchangriffen beruhen – Listen von häufigen Passwörtern aus anderen Datenverletzungen – viel schwieriger macht.
Jede Hash-Funktion kann auch so implementiert werden, dass mehrere Iterationen oder Durchläufe des Hash-Algorithmus für jedes Passwort durchgeführt werden. Dies wird auch als Arbeitsfaktor bezeichnet und hat das Ziel, das Ergebnis rechenintensiver zu machen, um es mit Brute-Force-Methoden zu knacken. Ein höherer Arbeitsfaktor erhöht zwar die Sicherheit, macht aber auch jede Hashing-Operation rechenintensiver und länger, da der Algorithmus mehrfach ausgeführt wird.
„Es gibt keine goldene Regel für den idealen Arbeitsfaktor – er hängt von der Leistung des Servers und der Anzahl der Benutzer der Anwendung ab“, so die OWASP in ihren Empfehlungen. „Die Bestimmung des optimalen Arbeitsfaktors erfordert Experimente auf dem/den spezifischen Server(n), die von der Anwendung verwendet werden. Als allgemeine Regel gilt, dass die Berechnung eines Hashes weniger als eine Sekunde dauern sollte, auf Seiten mit höherem Datenverkehr sollte sie jedoch deutlich geringer ausfallen.“
Salz und Pfeffer
Eine weitere Best Practice für die sichere Speicherung von Passwörtern besteht darin, jedes Passwort mit einer zufällig generierten Zeichenkette zu kombinieren, die als „Salt“ bezeichnet wird, und dann das Ergebnis zu hashen. Das Salt, das für jeden Benutzer und jedes Passwort eindeutig sein sollte, wird dann zusammen mit dem Hash gespeichert.
Durch das Salting von Passwörtern werden bestimmte Arten von Angriffen wesentlich erschwert oder unmöglich gemacht. Zum Beispiel können Angreifer Hashes für eine sehr große Anzahl von Kennwortkombinationen vorberechnen und sie dann in einer Datenbank, einer sogenannten Rainbow-Tabelle, speichern. Wenn sie später einen durchgesickerten Passwort-Hash finden, können sie einfach eine Suche in der Datenbank durchführen, um zu sehen, ob er mit einem der vorberechneten Hashes übereinstimmt. Da das Salting von Passwörtern auch den resultierenden Hash-Wert verändert, werden solche Angriffe ineffizient gemacht.
Das Salting verhindert auch, dass Angreifer doppelte Kennwörter in einer Datenbank entdecken. Selbst wenn zwei oder mehr Benutzer das gleiche Kennwort gewählt haben, hat der Server unterschiedliche Salts für sie generiert, und die resultierenden Hashes werden unterschiedlich sein. Es wird empfohlen, dass die Salts mindestens 16 Zeichen lang sein sollten, was die Komplexität und Länge der Klartextzeichenfolgen, die mit rechenintensiven Brute-Force-Methoden geknackt werden müssen, deutlich erhöht.
Um eine weitere Sicherheitsebene hinzuzufügen, können Entwickler zusätzlich zu den Salts auch alle Passwörter mit einer zufällig generierten Zeichenfolge von mindestens 32 Zeichen kombinieren, die als Pepper bezeichnet wird. Im Gegensatz zu einem Salt, das für jedes Passwort eindeutig ist, ist der Pepper für alle Passwörter gleich, sollte aber nicht in der Datenbank gespeichert werden. Das Ziel des Peppers ist es, es Angreifern schwer zu machen, Hashes zu knacken, selbst wenn sie die gesamte Datenbank der Anwendung einschließlich der Salts erhalten.
Der Pfeffer kann in einer Anwendungskonfigurationsdatei gespeichert werden, die mit entsprechenden Dateisystemberechtigungen geschützt ist, oder an einem sichereren Ort wie einem Hardware-Sicherheitsmodul (HSM).
„Ein alternativer Ansatz besteht darin, die Passwörter wie üblich zu hashen und dann die Hashes mit einem symmetrischen Verschlüsselungsschlüssel zu verschlüsseln, bevor sie in der Datenbank gespeichert werden, wobei der Schlüssel als Pepper fungiert“, so OWASP. „Dies vermeidet einige der Probleme mit dem traditionellen Ansatz des Peppers und ermöglicht eine viel einfachere Rotation des Peppers, wenn man glaubt, dass er kompromittiert ist.“
Aktualisieren von Hashes
Anwendungen, die einen unsicheren oder schwachen Hash-Algorithmus verwenden, sollten auf moderne Hash-Funktionen migriert werden. Eine Möglichkeit, dies zu tun, könnte darin bestehen, die alten Hashes als Eingabe für den neuen Hash-Algorithmus zu verwenden, also im Wesentlichen die alten Hashes neu zu hashen. Dies löst zwar das unmittelbare Problem, macht aber die resultierenden Hashes anfälliger für das Knacken, als wenn sie direkt aus der ursprünglichen Benutzereingabe generiert würden.
Aus diesem Grund wird empfohlen, dass Hashes mit dem neuen modernen Algorithmus neu generiert werden, wenn sich der Benutzer das nächste Mal anmeldet und sein Kennwort eingibt. Wenn der Benutzer nicht aktiv ist und sich für eine bestimmte Zeit nicht anmeldet, kann sein Passwort zurückgesetzt werden und er kann gezwungen werden, das Passwort zurückzusetzen, wenn er sich das nächste Mal anmeldet.
Zum Schluss noch die goldene Regel für alle Entwickler, wenn sie sich mit Kryptographie beschäftigen: Entwerfen Sie keine eigenen Algorithmen. Kryptographie ist sehr schwierig und die Algorithmen, die standardisiert und weit verbreitet sind, sind in der Regel das Ergebnis akademischer Forschungsbemühungen, die einer Peer Review durch andere Kryptographen und Kryptoanalytiker unterzogen werden.
*Lucian Constantin ist Senior-Autor bei CSO und berichtet über Informationssicherheit, Privatsphäre und Datenschutz.
Be the first to comment