Alternativen zum Senden eines Klartextkennworts während der Anmeldung

Jan 02 2021

Hinweis: Ich habe bereits gelesen. Ist es in Ordnung, ein Klartextkennwort über HTTPS zu senden? und https-Sicherheit - sollte das Passwort serverseitig oder clientseitig gehasht werden? , aber hier geht es um eine bestimmte Ersetzungsmethode (siehe unten).


Nachdem ich einen Artikel über eine neue Authentifizierungsmethode im Cloudflare-Blog gelesen hatte , habe ich mir die POSTAnforderungen angesehen, die während der Authentifizierung mit "Developer Tools> Network" gesendet werden. Viele beliebte Websites (Reddit, HN usw.) senden das Passwort in der (SSL-gesicherten) POSTAnfrage weiterhin im Klartext (siehe Abbildung unten).

Ist diese Anmeldemethode immer noch Industriestandard?

Ist die folgende Alternative sicherer als das Senden eines Klartextkennworts über HTTPS?

  • Anmeldung: Der Client generiert einen Zufall saltund sendet das Tupel (username, salt, hash(plain_password + salt))über eine POSTAnfrage. Dann erreicht das Klartext-Passwort nie den Server.

  • nachfolgende Anmeldungen: der Server zu senden , saltum wieder jeden Kunden, der mit einem gegebenen einzuloggen versucht username, so dass der Client - Hash mit dem gleichen Salz. Dies bedeutet, dass der Server saltjedem mitteilt , der versucht , sich mit einem bestimmten Benutzernamen anzumelden.

  • Vorteil: Der Server speichert ein gesalzenes + gehashtes Passwort (was Standard ist), aber auch der Server hat das Klartext-Passwort noch nie gesehen (wenn also der Server kompromittiert wird, ist das Risiko begrenzt).

Anmerkungen:

  • Da H = hash(plain_password + salt)sich der Server jetzt ein wenig wie ein neuer verhält plaintext(siehe die zweite Antwort von Zero Knowledge Password Proof: Warum ist das Hashing des Kennworts auf der Clientseite kein ZKP? ), kann der Server(username, salt, server_salt, hash(H + server_salt)) stattdessen in der Datenbank gespeichert werden (username, salt, H).

  • abzumildern für Replay - Attacken Risiken, senden kann der Server auch eine einzigartige nonce, zusammen mit saltfür jede Anmeldung, die nach einem Login - Versuch abläuft

  • Das Hauptziel hierbei ist, dass der Server niemals Zugriff auf das Klartextkennwort oder einen einfachen Hash davon hat (dies kann häufig mit einer einzelnen Regenbogentabelle für die gesamte Site umgekehrt werden). Ich bin mit dem Risiko einverstanden, dass ein Angreifer pro Benutzer eine Regenbogentabelle berechnen muss .

  • Beispiel für einen Angriff, den ich abschwächen möchte: Wenn der Server Zugriff auf ein Klartextkennwort hat und dieses kompromittiert ist (Beispiel Spectre / Meltdown vuln.), Kann das Klartextkennwort des Benutzers (möglicherweise auf anderen Websites wiederverwendet) gestohlen werden, bevor es gesalzen wird -hashed und in der Datenbank gespeichert.


Antworten

14 SteffenUllrich Jan 02 2021 at 14:38

Ich sehe nicht, wie Ihr Vorschlag besser ist als bestehende clientseitige Hashing-Ansätze, aber ich finde es komplexer zu implementieren als andere. Leider beschreiben Sie kein spezifisches Risiko, auf das Sie zugreifen möchten, daher gehe ich nur von den typischen Bedrohungen aus, die häufig auftreten.

Mann im mittleren Angreifer

In diesem Fall wird davon ausgegangen, dass ein Mann in der Mitte Zugriff auf den Datenverkehr hat, z. B. weil dadurch das TLS-Abfangen von vertrauenswürdigem Datenverkehr in einer Unternehmensfirewall beeinträchtigt wurde oder eine vertrauenswürdige Zertifizierungsstelle wie im Fall von Superfish festgehalten wurde .

In diesem Szenario erhält der Angreifer Zugriff auf Hdasselbe wie zuvor plain_password. Da Hfür die Authentifizierung alles erforderlich ist, ist der Angreifer erfolgreich und Ihr Ansatz bietet hier keinen zusätzlichen Schutz .

Ausblenden schwacher Passwörter und Wiederverwendung von Passwörtern

Ein häufiges Argument für clientseitiges Hashing besteht darin, dem Server kein schwaches oder wiederverwendetes Kennwort zur Verfügung zu stellen, sondern sich mit einem komplexen abgeleiteten Kennwort zu authentifizieren. Ihr Ansatz tut dies mit Hashing der plain_passwordmit einigen Benutzern erzeugen Zufall saltund dann senden Hund saltauf den Server , auf Passwort - Setup.

Während dies funktioniert, erfordert jede Authentifizierung jetzt einen zusätzlichen Schritt : Zuerst muss das zuvor für den Benutzer verwendete Salt vom Benutzer abgerufen werden, und dann kann es dieses verwenden, um das saltzu hashen plain_password. Dieser zusätzliche Schritt macht die Authentifizierung komplexer, da zuerst der Benutzer mit dem Server überprüft werden muss und später das Kennwort überprüft werden kann. Zusätzlich öffnet eine triviale Implementierung ein Informationsleck, da es möglich ist, ohne weitere Authentifizierung zu überprüfen, ob der Benutzer überhaupt existiert (zurückgegebenes Salz oder nicht).

Dieses Informationsleck kann vom Server geschlossen werden, der etwas Salz zurückgibt, unabhängig davon, ob der Benutzer vorhanden ist oder nicht. Natürlich kann dies nicht nur ein zufälliges Salz sein, da ein Angreifer andernfalls nur zweimal denselben Benutzer überprüfen und daraus schließen könnte, dass der Benutzer nicht existiert, wenn das zurückgegebene Salz anders wäre. Das Salz muss also tatsächlich für den nicht existierenden Benutzer festgelegt werden, dh vom Benutzernamen abgeleitet.

Dies zeigt auch einen Weg, um Ihren Ansatz zu vereinfachen : Anstatt ein zufälliges Salt vom Benutzer zu generieren, es auf dem Server zu speichern und später wieder abzurufen, könnte man das Salt einfach aus dem Benutzernamen auf der Clientseite ableiten . Ein einfacher salt=hash(username+domain)würde ausreichen , um ein Salz zu erzeugen , die pro Domäne eindeutig ist und somit beide machen saltund Hverschiedene , auch wenn usernameund plain_passwordin verschiedenen Domänen wiederverwendet zu erhalten. Und im Gegensatz zu Ihrem Ansatz ist keine zusätzliche Fahrt zum Server erforderlich, um zuerst das zuvor verwendete Salz für den Benutzer abzurufen.


Kurz gesagt: Dieser vereinfachte Ansatz sendet im Grunde genommen hash(plain_password+username+domain)anstelle des ursprünglichen Passworts. Die Domain wird hinzugefügt , um sicherzustellen , dass , selbst wenn usernameund plain_passwordüber mehrere Standorte wiederverwendet werden, das abgeleitete Passwort nicht wiederverwendet wird.

8 mti2935 Jan 02 2021 at 21:33

Dies ist genau das Problem, das Protokolle wie PAKE und SRP lösen sollen. Bei PAKE / SRP authentifizieren sich Client und Server gegenseitig anhand eines dem Client bekannten Kennworts (und einer Ableitung des dem Server bekannten Kennworts).

Der Client demonstriert dem Server, dass er das Kennwort kennt, ohne dass der Client das Kennwort (oder kennwortäquivalente Daten) an den Server sendet. Am Ende des Prozesses teilen sich der Client und der Server ein gemeinsames Geheimnis.

Der Server speichert das Kennwort (oder kennwortäquivalente Daten) nicht und ist nicht anfällig für Wörterbuchangriffe. Ein Lauscher oder ein Mann in der Mitte, der den über das Kabel gesendeten Klartext anzeigen kann, kann nicht genügend Informationen abrufen, um das Kennwort abzuleiten. Dies verhindert effektiv Man-in-the-Middle-Angriffe mit gefälschten Zertifikaten und verhindert, dass Phishing-Sites die Passwörter der Benutzer stehlen.

Eine gute Beschreibung der Implementierung von SRP durch 1password finden Sie unter https://blog.1password.com/developers-how-we-use-srp-and-you-can-too/

5 mentallurg Jan 02 2021 at 16:00

Neben der Antwort von Steffen Ullrich :

Wenn der Benutzer während der Anmeldung nur den Hash sendet, muss der Angreifer das Kennwort nicht kennen. Es reicht aus, die Passwortdatenbank zu stehlen. Während der Anmeldeanforderung sendet der Angreifer dann einfach den Hash aus der Datenbank. Der Server unterscheidet nicht, ob der Client das Kennwort verwendet und gehasht hat oder ob der Client (Angreifer) den Hash einfach gesendet hat.

Der Artikel über OPAQUE behebt auch dieses Problem: Der Diebstahl der Kennwortdatenbank hilft dem Angreifer nicht. Man müsste das einfache Benutzerpasswort kennen.

3 MargaretBloom Jan 03 2021 at 08:43

Wenn der Angreifer Ihren Server kompromittiert hat, hat er nicht nur die Kontrolle über die auf Ihrem Server ausgeführte Software, sondern auch über die auf den Clients ausgeführte Software.
Unabhängig davon, welches wunderschön gestaltete Authentifizierungsschema Sie entworfen haben, kann der Angreifer es ändern, bevor es an den Browser gesendet wird.
Sie haben jetzt ein Ei-Huhn-Problem: Sie können ein Passwort nicht sichern, wenn der Angreifer die Art und Weise kontrolliert, wie es gesammelt und an Ihren Server gesendet wird.

Wenn Sie sich Sorgen über einen Datenverstoß machen, dient Ihre Methode als Schutz, aber auch eine ordnungsgemäße Kennwort-Hashing-Serverseite.

Wenn Sie sich Sorgen über MITM-Angriffe machen, löst TLS diese.
Wenn Sie sich Sorgen über MITM-Angriffe über TLS machen, beginnt eine gute Verteidigung gegen sie immer mit einem Krav Maga-Handbuch. Ein Angreifer, der über genügend Ressourcen verfügt, um TLS dauerhaft zu brechen, hat kein Problem damit, von einer nicht ordnungsgemäß und speziell ausgebildeten Person das zu bekommen, was er will (ja, ich spreche von Folter, Erpressung, Entführung und Mord).

Wenn Sie sich Sorgen über einen Bedrohungsakteur machen, der nur die vom Server empfangenen Daten lesen kann, wirkt Ihr Ansatz (wie von Steffen korrigiert) gegen ihn. Dies ist jedoch ein seltsamer und seltener Umstand, der häufig auf einen stark falsch konfigurierten Server und schlechte Entwicklungspraktiken zurückzuführen ist (dh das Senden von Anmeldeinformationen über GET-Anforderungen und das öffentliche Speichern des Zugriffsprotokolls). Es ist einfacher, diese Fehler zu beheben, als ein Protokoll zu erfinden, um sie zu behandeln.

Beachten Sie, dass beide von Ihnen erwähnten Sicherheitslücken (eigentlich nur eine, da Meltdown technisch eine Variante von Spectre ist) letztendlich zu einer Eskalation lokaler Berechtigungen führen und dem Angreifer die volle Kontrolle über Ihren Webserver geben. Hervorheben, wie selten das Szenario ist, in dem ein Angreifer schreibgeschützt auf die von Ihrem Webserver empfangenen Daten zugreifen kann.

Der Grund, warum viele große Websites es nicht verwenden, liegt darin, dass es so gut wie nichts hinzufügt, außer unter bestimmten Umständen, bei denen es sich höchstwahrscheinlich um Fehlkonfigurationen handelt. Es ist auch erwähnenswert, dass Sie weit in der Verliererseite des Spiels sind, wenn ein Angreifer lesen kann, welche Daten auf Ihrem Server übertragen werden. Wohlgemerkt, es ist gut, mehrschichtige Schutzmaßnahmen zu haben, aber Ihr Hauptziel ist es nicht , dass dies überhaupt erst geschieht. Wenn Sie sich darauf konzentrieren, können Sie auch keine neuen Systeme erfinden.

Wie Steffen gezeigt hat, könnte Ihr vorgeschlagenes Schema wie ein seltsames Angriffsmodell wieder funktionieren. Ich würde immer noch verwenden, hash(hash(domain + username) + password)anstatt hash(domain + username + password)nur die entfernte Möglichkeit zu regieren, die domain + username + passwordimmer noch ein Wort in einem Wörterbuch ist.
Wie mti2935 gezeigt hat, ist SRP eine interessantere Alternative. Die zertifikatbasierte Authentifizierung (dh die vom Browser verwaltete) ist eine weitere Option (die ich besser finde, als sie manuell in einem möglicherweise fehlerhaften JS-Skript durchzuführen, wie Sie in den Kommentaren vorgeschlagen haben).