Sie pflegen eine vorhandene Anwendung mit einer etablierten Benutzerbasis. Mit der Zeit wird entschieden, dass die aktuelle Kennwort-Hashing-Technik veraltet ist und aktualisiert werden muss. Außerdem möchten Sie aus UX-Gründen nicht, dass vorhandene Benutzer gezwungen werden, ihr Kennwort zu aktualisieren. Das gesamte Passwort-Hashing-Update muss hinter dem Bildschirm erfolgen.
Nehmen Sie für Benutzer ein 'vereinfachtes' Datenbankmodell an, das Folgendes enthält:
- ICH WÜRDE
- Passwort
Wie geht man vor, um eine solche Anforderung zu lösen?
Meine aktuellen Gedanken sind:
- Erstellen Sie eine neue Hash-Methode in der entsprechenden Klasse
- Aktualisieren Sie die Benutzertabelle in der Datenbank, um ein zusätzliches Kennwortfeld aufzunehmen
- Sobald sich ein Benutzer erfolgreich mit dem veralteten Kennwort-Hash anmeldet, füllen Sie das zweite Kennwortfeld mit dem aktualisierten Hash aus
Dies führt zu dem Problem, dass ich nicht sinnvoll zwischen Benutzern mit und Benutzern ohne Passwortaktualisierung unterscheiden kann und daher gezwungen bin, beide zu überprüfen. Dies scheint schrecklich fehlerhaft.
Darüber hinaus bedeutet dies im Grunde genommen, dass die alte Hashing-Technik so lange bestehen bleiben muss, bis jeder einzelne Benutzer sein Passwort aktualisiert hat. Erst in diesem Moment konnte ich anfangen, die alte Hashing-Prüfung zu entfernen und das überflüssige Datenbankfeld zu entfernen.
Ich suche hier hauptsächlich nach einigen Designtipps, da meine aktuelle "Lösung" schmutzig ist, unvollständig und was nicht, aber wenn tatsächlicher Code zur Beschreibung einer möglichen Lösung erforderlich ist, können Sie eine beliebige Sprache verwenden.
quelle
Antworten:
Ich würde vorschlagen, ein neues Feld "hash_method" hinzuzufügen, mit einer 1, um die alte Methode zu kennzeichnen, und einer 2, um die neue Methode zu kennzeichnen.
Wenn Sie sich für diese Art von Dingen interessieren und Ihre Anwendung relativ langlebig ist (was es anscheinend bereits ist), wird dies wahrscheinlich wieder vorkommen, da Kryptografie und Informationssicherheit ein sich entwickelndes, eher unvorhersehbares Gebiet sind. Es gab eine Zeit, in der ein einfacher Durchlauf durch MD5 Standard war, wenn überhaupt Hashing verwendet wurde! Dann könnte man meinen, sie sollten SHA1 verwenden, und jetzt gibt es Salting, Global Salt + Individual Random Salt, SHA3, verschiedene Methoden der kryptofertigen Zufallszahlengenerierung Beheben Sie dies auf erweiterbare, wiederholbare Weise.
Nehmen wir also an, Sie haben jetzt so etwas wie (der Einfachheit halber in Pseudo-Javascript, hoffe ich):
Jetzt, da Sie feststellen, dass es eine bessere Methode gibt, müssen Sie nur noch ein kleines Refactoring durchführen:
Bei der Erstellung dieser Antwort wurden keine Geheimagenten oder Programmierer verletzt.
quelle
newHash(oldHash, salt)
odernewHash(password, salt)
Wenn Sie genug Wert darauf legen, das neue Hashing-Schema so schnell wie möglich für alle Benutzer bereitzustellen (z. B. weil das alte wirklich unsicher ist), gibt es tatsächlich eine Möglichkeit für die sofortige "Migration" jedes Kennworts.
Die Idee ist im Grunde, den Hash zu hacken . Anstatt
p
beim nächsten Login darauf zu warten, dass Benutzer ihr vorhandenes Passwort ( ) angeben, verwenden Sie sofort den neuen Hashing-Algorithmus (H2
) für den vorhandenen Hash, der bereits vom alten Algorithmus (H1
) erstellt wurde:Nach dieser Konvertierung können Sie die Kennwortüberprüfung weiterhin problemlos durchführen. Sie müssen nur
H2(H1(p'))
anstelle der vorherigen Berechnungen durchführen,H1(p')
wenn der Benutzer versucht, sich mit einem Kennwort anzumeldenp'
.Theoretisch könnte diese Technik auf mehrere Migrationen angewendet werden (
H3
,H4
usw.). In der Praxis sollten Sie die alte Hash-Funktion aus Gründen der Leistung und Lesbarkeit entfernen. Glücklicherweise ist dies ganz einfach: Berechnen Sie bei der nächsten erfolgreichen Anmeldung einfach den neuen Hash des Benutzerpassworts und ersetzen Sie den vorhandenen Hash eines Hashs durch diesen:Sie benötigen außerdem eine zusätzliche Spalte, um sich zu merken, welchen Hash Sie speichern: den des Passworts oder des alten Hashs. Im unglücklichen Fall eines Datenbanklecks sollte diese Spalte die Arbeit des Crackers nicht einfacher machen. Unabhängig von seinem Wert müsste der Angreifer den sicheren
H2
Algorithmus und nicht den alten umkehrenH1
.quelle
Ihre Lösung (zusätzliche Spalte in der Datenbank) ist vollkommen akzeptabel. Das einzige Problem dabei ist das, das Sie bereits erwähnt haben: Das alte Hashing wird immer noch für Benutzer verwendet, die sich seit der Änderung nicht authentifiziert haben.
Um dies zu vermeiden, müssen Sie möglicherweise warten, bis Ihre aktivsten Benutzer auf den neuen Hashing-Algorithmus umgestellt haben.
Entfernen Sie die Konten von Benutzern, die sich zu lange nicht authentifiziert haben. Es ist nichts Falsches daran, einen Account eines Benutzers zu entfernen, der drei Jahre lang nicht auf die Website gekommen ist.
Senden Sie eine E-Mail an die verbleibenden Benutzer, die sich eine Weile nicht authentifiziert haben, und teilen Sie ihnen mit, dass sie möglicherweise an etwas Neuem interessiert sind. Dies wird dazu beitragen, die Anzahl der Konten, die das ältere Hashing verwenden, weiter zu reduzieren.
Seien Sie vorsichtig: Wenn Sie eine spamfreie Option haben, die Benutzer auf Ihrer Website überprüfen können, senden Sie die E-Mail nicht an Benutzer, die sie überprüft haben.
Schließlich zerstören Sie einige Wochen nach Schritt 2 das Kennwort für die Benutzer, die noch die alte Technik verwenden. Wann und wenn sie versuchen, sich zu authentifizieren, werden sie feststellen, dass ihr Passwort ungültig ist. Wenn sie immer noch an Ihrem Dienst interessiert sind, können sie ihn zurücksetzen.
quelle
Sie werden wahrscheinlich nie mehr als ein paar Hash-Typen haben, daher können Sie dies lösen, ohne Ihre Datenbank zu erweitern.
Wenn die Methoden unterschiedliche Hash-Längen haben und die Hash-Länge jeder Methode konstant ist (z. B. Übergang von md5 zu hmac-sha1), können Sie die Methode anhand der Hash-Länge unterscheiden. Wenn sie dieselbe Länge haben, können Sie den Hash zuerst mit der neuen Methode und dann mit der alten Methode berechnen, wenn der erste Test fehlgeschlagen ist. Wenn in einem Feld (nicht angezeigt) angegeben ist, wann der Benutzer zuletzt aktualisiert / erstellt wurde, können Sie dies als Indikator für die zu verwendende Methode verwenden.
quelle
Ich habe so etwas gemacht und es gibt eine Möglichkeit festzustellen, ob es sich um den neuen Hash handelt UND ihn noch sicherer zu machen. Ich vermute, sicherer ist eine gute Sache für Sie, wenn Sie sich die Zeit nehmen, Ihren Hash zu aktualisieren ;-)
Fügen Sie Ihrer DB-Tabelle eine neue Spalte mit dem Namen "salt" hinzu, und verwenden Sie sie als pro Benutzer zufällig generiertes Salt. (beugt Regenbogentischangriffen so gut wie vor)
Auf diese Weise wäre mein neues Passwort der Hash von "pass1233333", wenn mein Passwort "pass123" und "random salt" 3333 ist.
Wenn der Benutzer ein Salz hat, wissen Sie, dass es der neue Hash ist. Wenn das Salt des Benutzers null ist, wissen Sie, dass es der alte Hash ist.
quelle
Egal wie gut Ihre Migrationsstrategie ist, wenn die Datenbank bereits gestohlen wurde (und Sie nicht negativ nachweisen können, dass dies noch nie geschehen ist), sind Kennwörter, die mit unsicheren Hash-Funktionen gespeichert wurden, möglicherweise bereits gefährdet. Die einzige Abhilfe besteht darin, dass Benutzer ihre Kennwörter ändern müssen.
Dies ist kein Problem, das (nur) durch Schreiben von Code gelöst werden kann. Die Lösung besteht darin, Benutzer und Kunden über die Risiken zu informieren, denen sie ausgesetzt waren. Sobald Sie dazu bereit sind, können Sie die Migration durchführen, indem Sie einfach das Kennwort jedes Benutzers zurücksetzen, da dies die einfachste und sicherste Lösung ist. Bei allen Alternativen geht es wirklich darum, die Tatsache zu verbergen, dass Sie Mist gebaut haben.
quelle