Wie das Anmeldekennwort-Hashing funktionieren soll
Beachten Sie, dass ich in allen Snippets absichtlich Sicherheitsfunktionen ausschließe, weil ich es kompakt halten möchte. Verlassen Sie sich bei nichts auf diese Codefragmente.
In normalen Netzwerkanwendungen, die Kennwort-Hashing verwenden, wird das Benutzerkennwort auf der Clientseite gehasht, bevor es an den Server gesendet wird, oder es wird ohne Hashing gesendet als Verschlüsselung des Nur-Text-Passworts für den Server?
Nein, es ist eine gehashte Serverseite. Sie senden das Kennwort im Klartext oder über HTTPS an den Server. Der Server generiert dann einen Hash für das Kennwort wie folgt:
public void RegisterAccount (Zeichenfolgenbenutzername, Zeichenfolgenkennwort, Zeichenfolgen-E-Mail) {if (! Database.EmailExists (E-Mail) &&! Database .UsernameExists (Benutzername)) {Database.AddNewUser (Benutzername, Hash.GenerateHash (Passwort), E-Mail); }}
Angenommen, Database.AddNewUser (Zeichenfolge, Zeichenfolge, Zeichenfolge);
fügt den Benutzernamen, das Hash-Kennwort und die E-Mail in die Datenbank ein. Der Hash wird basierend auf dem Passwort generiert.
Nehmen wir an, Sie geben als Passwort "Hack mich bitte nicht" ein. bcrypt verwandelt daraus $ 2a $ 08 $ BOHyNdXAVkWOUgPG / hvsjew7ZpngqJIgueY6m76xd4y3UllXUZLBy
oder eine andere Variante, die auf dem Salz basiert. Die Datenbank sieht jetzt folgendermaßen aus:
+ -------------- + ----------------- ----------------------------------------- + ---- ---------------- + | Benutzer | Passwort | E-Mail | + -------------- + -------------------------------- ------------------------------ + ------------------- - + | markbuffalo | $ 2a $ 08 $ BOHyNdXAVkWOUgPG / hvsjew7ZpngqJIgueY6m76xd4y3UllXUZLBy | mark@buffalo.gov | + -------------- + ---------------------------- ---------------------------------- + --------------- ----- +
Normalerweise rufen Sie die Datenbank auf, um das Kennwort für diesen Benutzernamen zu lesen. Sobald Sie die Datenbank aufgerufen haben, verwenden Sie eine Funktion wie Hash.ValidateHash ()
, um festzustellen, ob sie übereinstimmt. Wenn es übereinstimmt, können Sie sich mit diesem nicht gehashten Passwort anmelden.
Warum können Sie den Hash nicht einfach übergeben, um sich anzumelden?
In einigen sehr unglücklichen Fällen.
Die Hauptfrage, die ich habe, ist, ob ein Angreifer die Hash-Passwörter entdeckt. Warum kann er dann nicht einfach Hash an den Server senden, um sich bei clientseitigem Hashing zu authentifizieren?
Dies ist möglich, kann jedoch nur in schweren Fällen von massiv epischen Fehlern im Auftrag der Entwickler auftreten. Tatsächlich habe ich das schon einmal gesehen und ich werde Ihnen zeigen, wie dies über Code geschehen kann:
public void Login (String-Benutzername, String-Passwort) {if (Database.LoginMatches ( Benutzername, Passwort) || Database.LoginMatches (Benutzername, Hash.ValidateHash (Passwort))) {logMeIn (); }}
Im obigen Snippet möchte der Login überprüfen, ob entweder der Benutzer den Hash oder das Kennwort hat, das in dem in der Datenbank gespeicherten Hash validiert wird. Dies ist nicht der richtige Weg, dies zu tun. Tatsächlich ist es einer der schlimmsten Fälle von epischem Versagen, die ich je in meinem Leben gesehen habe.
Mit diesem Code können Sie einfach den Hash oder das Passwort eingeben und sich anmelden Tabelle. Eine der folgenden Anmeldungen funktioniert ordnungsgemäß:
-
Login ("markbuffalo", "$ 2a $ 08 $ BOHyNdXAVkWOUgPG / hvsjew7ZpngqJIgueY6m76xd4y3UllXUZLBy");
-
Login ("markbuffalo", @ "hack mich bitte nicht");
ol> Das ist der falsche Ansatz. Es soll nicht passieren. Beim. Alles. Trotzdem haben einige Entwickler diesen Ansatz aus Gründen gewählt, die ich nicht kenne.
Was ist der richtige Ansatz für die Hash-Validierung?
Wie Rápli András sagte, stimmt h (x)
nicht mit h (h (x))
überein. Der richtige Ansatz besteht darin, das eingehende Kennwort anhand des Hashs zu überprüfen, um festzustellen, ob sie übereinstimmen. Wenn sie nicht übereinstimmen, verwenden Sie keine ODER
Magie ( ||
). Erlauben Sie ihnen einfach nicht, sich anzumelden.