Secure Coding: Sicherere Passwörter mit Salt, Pepper und Hashing
Sicherheit durch Passwort-Hashing ist unverzichtbar. Best Practices fĂĽr den gezielten Einsatz von Salt und Pepper steigern das Schutzniveau weiter.
(Bild: erstellt mit Chat-GPT / DALL-E)
- Sven Ruppert
Der Secure-Coding-Beitrag "Passwort-Hashing zum Schutz vor Brute-Force und Rainbow-Tabellen" hat bereits dargelegt, warum Passwörter nie direkt unverschlüsselt, sondern als Hashwert im Persistenzlayer gespeichert werden sollten. Ebenfalls zur Sprache kam dabei, welche Bedeutung Salt-Werte – zufällige Zeichenketten – beim Hashing haben, um die Sicherheit weiter zu erhöhen. Der folgende Beitrag zeigt nun, was Entwicklerinnen und Entwickler beim Erzeugen und Anwenden von Salt-Werten beachten sollten.
Warum benötigt man Hashing für Passwörter und einen Salt-Wert?
Als kurze Wiederholung: Passwort-Hashing ist eine essenzielle Technik zum sicheren Speichern von Passwörtern. Anstatt ein Passwort im Klartext abzulegen, wird es durch eine Einweg-Hashfunktion in eine Zeichenkette umgewandelt, die sich nicht ohne Weiteres zurückrechnen lässt. So sind Passwörter vor unbefugtem Zugriff geschützt, auch wenn eine Datenbank kompromittiert wird.
Da identische Passwörter bei der Hash-Berechnung stets denselben Hash ergeben, könnten beispielsweise Angreifer, die eine Datenbank mit gehashten Passwörtern erbeutet haben, durch den Vergleich der Hashes einfach herausfinden, welche Benutzer dasselbe Passwort verwenden. Dies erleichtert massive und gezielte Angriffe auf spezifische Nutzer. Für höhere Sicherheit kommt daher der sogenannte Salt-Wert ins Spiel, eine zufällige Zeichenkette, die vor der Hash-Berechnung an ein Passwort angehängt wird. So lassen sich auch für identische Passwörter unterschiedliche Hash-Werte erzeugen und der Schutz gegen verschiedene Angriffstechniken wie etwa Rainbow Table erhöhen.
Videos by heise
Best Practices fĂĽr den Umgang mit Salt-Werten
Rainbow Tables – vorberechnete Tabellen mit Hash-Werten zu einer großen Anzahl gängiger Passwörter – nutzen Angreifer, um möglichst effizient ein Passwort aus seinem Hash zu rekonstruieren. Wurde bei der Hash-Berechnung jedoch ein Salt-Wert hinzugefügt, ist kein unmittelbarer Rückschluss auf das Passwort mehr möglich. Ferner schützen Salt-Werte vor sogenannten Dictionary-Angriffen, bei denen Angreifer versuchen, eine Liste häufig genutzter Passwörter durchzuprobieren, um deren Hashes mit denen in einer gestohlenen Datenbank abzugleichen.
Für den sicheren Umgang mit Salt-Werten ist es erstens wichtig, für jedes Passwort einen einzigartigen Salt-Wert zu verwenden. Zweitens muss der Wert zufällig und ausreichend lang sein. Empfohlen wird eine Länge von mindestens 16 Bytes, um die Gefahr von Kollisionen und vorhersehbaren Mustern zu vermeiden. Kryptografisch sichere Zufallszahlengeneratoren stellen darüber hinaus sicher, dass die Salt-Werte nicht zu erraten sind. Drittens sollte der Salt-Wert gemeinsam mit dem gehashten Passwort gespeichert werden. Da er keine geheime Information ist, besteht kein Risiko, wenn er öffentlich zugänglich ist. Er darf jedoch nicht mehrfach für verschiedene Passwörter wiederverwendet werden.
Um das Hashing-Verfahren auch gegen Brute-Force-Angriffe zu härten, empfehlen sich rechenintensive Hash-Algorithmen – sie legen die Hürden für Angriffe durch wiederholte Berechnungen höher. Schließlich kann ergänzend zum Salt- auch noch ein Pepper-Wert genutzt werden, der als geheimer Schlüssel serverseitig hinterlegt ist und nicht mit den Hash-Daten gespeichert wird. Regelmäßige Sicherheitsüberprüfungen, Aktualisierungen der Hashing-Methoden und das Anpassen von Parametern wie etwa der Anzahl der Iterationen runden die empfehlenswerten Sicherheitsmaßnahmen ab.
Was ist der Pepper-Wert und wie schĂĽtzt er?
Der Pepper-Wert ist ein geheimer Schlüssel, der in Kombination mit einem Passwort verwendet wird, um die Sicherheit des Hashing-Prozesses zu erhöhen. Im Gegensatz zum Salt-Wert, der individuell für jedes Passwort generiert und gespeichert wird, bleibt der Pepper-Wert für alle Passwörter eines Systems gleich und wird separat, beispielsweise in der Serverkonfiguration, gespeichert.
Der Hauptzweck besteht darin, Angriffe auf gestohlene Hash-Werte zu erschweren. Falls ein Angreifer Zugriff auf eine Datenbank mit Passwort-Hashes erhält, kann er die Hashes nicht ohne Weiteres entschlüsseln, da der Pepper-Wert nicht in der Datenbank gespeichert ist. Dies macht es für Angreifer deutlich schwieriger, Hashes durch die bereits erwähnten Dictionary- oder Brute-Force-Angriffe zu knacken, da ihnen ein wesentlicher Teil der Berechnung fehlt.
Ein weiterer Vorteil des Pepper-Werts besteht darin, dass er sich regelmäßig austauschen lässt, um zu verhindern, dass langfristig gespeicherte Hashes kompromittiert werden, falls ein Angreifer sich Zugriff auf ältere Datensätze verschafft.
Best Practices fĂĽr den Umgang mit Pepper-Werten
Im Unterschied zu Salt-Werten sollten Pepper-Werte nicht in der Datenbank gespeichert werden, sondern sicher in der Serverkonfiguration oder speziellen Sicherheitslösungen wie einem Hardware Security Module (HSM) hinterlegt sein. Auch sollte der Pepper-Wert niemals direkt im Quellcode oder der Hardware für den Betrieb der Anwendung gespeichert werden. Stattdessen empfiehlt sich die Nutzung sicherer Umgebungsvariablen oder eines Secrets-Management-Systems. Dadurch ist sichergestellt, dass Angreifer, die sich Zugriff auf die Datenbank verschafft haben, nicht ebenfalls den Pepper-Wert erbeuten.
Ein wichtiger Aspekt ist zudem die regelmäßige Aktualisierung des Pepper-Werts. Da er (oftmals, aber nicht zwingend) für alle Passwörter eines Systems gleich ist, sollte er in regelmäßigen Abständen geändert werden, um auch langfristig Sicherheit zu gewährleisten. Dazu ist allerdings eine erneute Hash-Berechnung für alle gespeicherten Passwörter erforderlich, die nach einem gut durchdachten Rotationsmechanismus erfolgen sollte.
Der Einsatz von Pepper-Werten ist nur in Verbindung mit Passwort-Hashing und Salt-Werten sinnvoll. Ein Pepper-Wert allein erhöht die Sicherheit nicht.
Welche Gefahr droht durch Kollisionen und wie lassen sie sich vermeiden?
Kollisionen treten im Zusammenhang mit Hashing auf, wenn zwei verschiedene Eingabewerte denselben Hash-Wert erzeugen. Bei der Speicherung von Passwörtern stellen sie ein Sicherheitsrisiko dar. Falls ein Angreifer eine Kollision erzeugen kann, könnte er eine alternative Eingabe mit demselben Hash-Wert generieren und sich dadurch unbefugt Zugang verschaffen. Man spricht dann von einem Kollisionsangriff.
Da Hash-Funktionen zudem eine begrenzte Ausgabemenge haben, während die Menge möglicher Eingaben unendlich groß ist, sind Kollisionen theoretisch unvermeidbar. In der Praxis lässt sich jedoch durch die Wahl einer geeigneten kryptografischen Hash-Funktion die Wahrscheinlichkeit einer Kollision minimieren. Ältere Algorithmen wie MD5 oder SHA-1 gelten als unsicher, da für sie bereits praktikable Kollisionsangriffe existieren. So wurde 2017 durch das SHAttered-Projekt nachgewiesen, dass sich SHA-1-Kollisionen bereits mit vergleichsweise moderaten Rechenressourcen erzeugen lassen. MD5-Kollisionen sind sogar noch einfacher zu erreichen. Erst neuere Algorithmen wie SHA-256 oder Argon2 bieten eine ausreichende Sicherheit. Bei SHA-256 etwa sind 2^128 Versuche notwendig, um eine Kollision zu finden. Die Wahrscheinlichkeit eines Kollisionsangriffes ist damit extrem niedrig.
Wie gehe ich mit alten Passwörtern sowie Salt- und Pepper-Werten in einem System um?
Der Umgang mit alten Salt- und Pepper-Werten sowie Passwort-Hashes in einem System erfordert besondere Sorgfalt, um sowohl Sicherheit als auch Benutzerfreundlichkeit zu gewährleisten. Entwicklerinnen und Entwickler sollten dazu auf die folgenden bewährten Verfahren zurückgreifen.
Zunächst ist sicherzustellen, dass veraltete Hash-Algorithmen oder unsichere Methoden schrittweise durch modernere ersetzt werden. Falls noch ein schwacher Hash-Algorithmus zum Einsatz kommt, sollte ein Migrationsprozess implementiert werden, bei dem Passwörter beim nächsten erfolgreichen Login mit einem stärkeren Algorithmus und einem neuen Salt erneut gehasht und gespeichert werden.
Alte Salt-Werte lassen sich so lange weiterverwenden, wie sie als ausreichend gelten. Sind sie jedoch zu kurz oder vorhersehbar, sollten sie durch neue, sicherere Salt-Werte ersetzt werden. Dies kann ebenfalls beim nächsten Login oder Passwortwechsel eines Benutzers geschehen, um eine schrittweise Umstellung zu ermöglichen.
Pepper-Werte sollten regelmäßig aktualisiert werden, um die Sicherheit weiter zu erhöhen. Da sich neue Pepper-Werte nicht rückwirkend auf alte Hashes anwenden lassen, muss die Aktualisierung schrittweise erfolgen, indem neue Passwörter mit einem neuen Pepper-Hash versehen werden, während alte regelmäßig überprüft werden. Um das Risiko einer Kompromittierung zu minimieren, sollten alte Pepper-Werte jedoch nicht dauerhaft gespeichert werden, sondern nur so lange, bis alle betroffenen Passwörter mit einem neuen Pepper-Hash aktualisiert sind.
Alternativ lässt sich die vollständige Erneuerung aller Hashes erreichen, indem Benutzer dazu gezwungen werden, ihre Passwörter nach einer bestimmten Zeit oder nach einer Sicherheitswarnung zurückzusetzen. Dies stellt sicher, dass alle Passwörter auf Basis der neuesten Sicherheitsstandards gespeichert sind.
Zu guter Letzt ist es ratsam, auch alte Hashes nicht unbegrenzt aufzubewahren. Nach einer angemessenen Übergangszeit und nachdem sichergestellt ist, dass alle Benutzer ihre Passwörter aktualisiert haben, sollten veraltete Hashes sicher gelöscht werden, um das Risiko eines Missbrauchs zu minimieren.
Vor- und Nachteile der verschiedenen Migrationsstrategien
Es gibt verschiedene Strategien zur Migration von Passwort-Hashes, die sich in Bezug auf Benutzerfreundlichkeit, Wirtschaftlichkeit und Sicherheit unterscheiden:
Schrittweise Migration beim nächsten Login
Bei dieser Methode erfolgt die Umstellung auf ein sicheres Hashing-Verfahren automatisch im Hintergrund, sobald sich ein Benutzer anmeldet. Die Systembelastung bleibt moderat, da nur aktive Nutzer betroffen sind. Allerdings bedeutet dies, dass alte unsichere Hashes so lange im System verbleiben, bis ein Benutzer sich einloggt – inaktive Nutzer profitieren nicht von der Migration, und es besteht ein längerer Zeitraum, in dem weniger sichere Hashes noch existieren.
Erzwungene Passwort-Aktualisierung
Diese Methode stellt sicher, dass alle Benutzer ihre Passwörter umgehend ändern müssen, um zu gewährleisten, dass sie mit aktuellen und sicheren Hashes gespeichert werden. Potenzielle Sicherheitsprobleme lassen sich auf diese Weise schnell beheben. Allerdings kann dies zu erhöhtem Supportaufwand sowie zu Unmut seitens der Nutzer führen, falls bei der Änderung Probleme auftreten und möglicherweise Passwörter mehrfach zurückgesetzt werden müssen.
Automatisches Neuberechnen aller Hashes
Bei dieser Methode werden alle gespeicherten Passwörter sofort auf einen sicheren Standard umgestellt, ohne dass eine Benutzerinteraktion erforderlich ist. So ist sichergestellt, dass sämtliche Passwörter den neuesten Sicherheitsanforderungen genügen. Allerdings gibt es Herausforderungen: Falls die Hashing-Methode einen Pepper-Wert verwendet, kann die Neuberechnung nicht ohne Kenntnis des Klartext-Passworts erfolgen. Zudem erfordert diese Strategie einen hohen Ressourcenaufwand, da die gesamte Datenbankmigration auf einmal durchgeführt werden muss, was zumindest temporär zu Leistungseinbußen führen kann.
Hybride Strategie
Diese Methode kombiniert die Vorteile der schrittweisen und der erzwungenen Migration. Während aktive Nutzer automatisch beim nächsten Login auf das neue Hashing-Verfahren umgestellt werden, müssen jene mit älteren oder inaktiven Konten eine Passwortänderung durchführen, um auf den neuen Sicherheitsstandard zu wechseln. Das Vorgehen reduziert einerseits die Belastung des Systems, gewährleistet aber dennoch eine umfassende Aktualisierung. Allerdings geht mit dieser Strategie eine komplexere Implementierung einher, da verschiedene Benutzergruppen unterschiedlich behandelt werden müssen.
Eine sorgfältige Auswahl der Migrationsstrategie unter Berücksichtigung der beschriebenen Faktoren erhöht die Sicherheit des Systems, ohne die Benutzerfreundlichkeit oder Wirtschaftlichkeit im Einzelfall unnötig zu beeinträchtigen.