it-swarm-eu.dev

https-Sicherheit - Sollte das Passwort serverseitig oder clientseitig gehasht werden?

Ich erstelle eine Webanwendung, bei der sich Benutzer anmelden müssen. Die gesamte Kommunikation erfolgt über https. Ich verwende bcrypt, um Passwörter zu hashen.

Ich stehe vor einem Dilemma - ich dachte früher, es sei sicherer, einen Passwort-Hash clientseitig (mit JavaScript) zu erstellen und ihn dann einfach mit dem Hash auf der DB-Serverseite zu vergleichen. Ich bin mir jedoch nicht sicher, ob dies besser ist, als ein Klartext-Passwort über https zu senden und es dann serverseitig zu hashen.

Meine Argumentation ist, dass ein Angreifer, wenn er den https-Verkehr abfangen kann (= Klartext-Passwort lesen), beispielsweise auch das JavaScript so ändern kann, dass es das Klartext-Passwort neben dem Hash-Passwort sendet - wo er es abfangen kann.

Der Grund gegen Hashing auf der Clientseite ist einfach die Benutzerfreundlichkeit. Wenn ich clientseitig hashe, muss ich zwei separate Bibliotheken für das Hashing verwenden. Dies ist kein unüberwindbares Problem, aber es ist ein Ärgernis.

Gibt es einen Sicherheitsgewinn bei der Verwendung von clientseitigem Hashing? Warum?

Sollte ich dann auch Challenge-Response verwenden?

PDATE : Was mich am meisten interessiert, ist Folgendes: Fügen diese Techniken (clientseitiges Hashing, Anfrage-Antwort) einen signifikanten Sicherheitsgewinn hinzu, falls https verwendet wird? Wenn ja warum?

116
johndodo

Wenn Sie auf der Clientseite hashen, wird das Hash-Passwort zum eigentlichen Passwort (wobei der Hashing-Algorithmus nichts anderes als ein Mittel ist, um eine vom Benutzer gehaltene Mnemonik in das tatsächliche Passwort umzuwandeln).

Dies bedeutet, dass Sie das vollständige Kennwort "Klartext" (den Hash) in der Datenbank speichern und in erster Linie alle Vorteile des Hashings verloren haben.

Wenn Sie sich für diesen Weg entscheiden, können Sie genauso gut auf Hashing verzichten und einfach das unformatierte Passwort des Benutzers übertragen und speichern (was ich übrigens nicht besonders empfehlen würde).

124
Nicole Calinoiu

Das Hashing auf dem Client ist nur dann sinnvoll, wenn Sie dem Server in irgendeiner Weise nicht vertrauen und ihm nicht das "tatsächliche" Kennwort anzeigen möchten (das Kennwort, an das sich der menschliche Benutzer erinnert). Warum möchten Sie das Passwort nicht genau der Site anzeigen, auf der das Passwort verwendet wird? Weil Sie das Passwort an anderer Stelle wiederverwendet haben ! Nun, das ist normalerweise schlecht, aber es gibt eine relativ sichere Version, die in unzähligen Browsererweiterungen oder Lesezeichen wie dieses enthalten ist oder dieser (Ich bürge nicht für ihre Qualität). Hierbei handelt es sich um Tools, bei denen sich der menschliche Benutzer ein "Hauptkennwort" merkt, aus dem ein standortspezifisches Kennwort generiert wird, wobei der Standortdomänenname als eine Art Salz verwendet wird, sodass zwei unterschiedliche Standorte unterschiedliche Kennwörter erhalten.

Dieses Szenario ist zwar sinnvoll, jedoch nicht mit Javascript, das vom Server selbst gesendet wird. In der Tat besteht der Punkt beim Hashing der Kennwort-Clientseite darin, dass der Server möglicherweise feindlich eingestellt ist (z. B. von einem Angreifer untergraben wird), und daher ist der von diesem Server gesendete Javascript-Code zumindest verdächtig. Sie möchten Ihr wertvolles Passwort nicht in feindliches Javascript eingeben ...


Ein weiterer Fall für clientseitiges Hashing ist langsames Hashing. Da Passwörter per Definition schwach sind, möchten Sie Wörterbuchangriffe vereiteln. Sie gehen davon aus, dass der Bösewicht eine Kopie der Serverdatenbank erhalten hat und auf seinen eigenen Computern "Passwörter ausprobiert" (siehe dieser Blog-Beitrag für eine Diskussion dazu). Um den Gegner zu verlangsamen, verwenden Sie einen von Natur aus langsamen Hashing-Prozess (z. B. bcrypt ). Dadurch wird die Verarbeitung jedoch für alle, einschließlich des Servers, langsam. Um dem Server zu helfen, möchten Sie möglicherweise einen Teil der Arbeit auf dem Client auslagern und daher zumindest einen Teil davon in Javascript-Code ausführen, der im Client-Browser ausgeführt wird ...

Leider ist Javascript bei dieser Art von Arbeit furchtbar langsam (normalerweise 20- bis 100-mal langsamer als anständiger C-Code), und das Client-System kann keinen wesentlichen Teil zum Hashing-Aufwand beitragen. Die Idee ist solide, muss aber auf eine bessere Technologie warten (es hätte mit einem Java Client funktioniert: mit einer anständigen JVM, optimiert Java Code) ist etwa 2 bis 4 Mal langsamer als optimierter C-Code (für einen Hashing-Job).


Zusammenfassend lässt sich sagen, dass es keinen wirklich guten Grund gibt, clientseitiges Passwort-Hashing anhand von Javascript-Code durchzuführen, der vom Server selbst gesendet wird. Senden Sie einfach das Passwort "wie es ist" über einen HTTPS-Tunnel an den Server (die Anmeldeseite, die Formularziel-URL und jede Seite, die durch das Passwort geschützt ist, müssen alle bedient werden über SSL, sonst haben Sie dringendere Sicherheitsprobleme als die Verwendung von Passwörtern).

32
Thomas Pornin

Ich finde alle Ihre Bedenken vernünftig, aber meine Empfehlung wäre, es serverseitig zu tun.

Es besteht immer eine ziemlich große Chance, dass ein Benutzer sein Terminal entsperrt lässt, um Manipulationen zu ermöglichen. Und auch; Wenn Ihre Hashing-Logik clientseitig ist, legen Sie sie offen.

Eine andere Möglichkeit wäre, die Passwörter serverseitig zu generieren. dann senden Sie kein Klartext-Passwort ein. Sie müssen dem Benutzer jedoch weiterhin das Kennwort mitteilen. Und da die meisten Benutzer immer noch keine verschlüsselten E-Mails verwenden, halte ich das für weniger sicher.

Ich habe Lösungen zum Senden von Passwörtern über einen verschlüsselten Tunnel an ein Mobiltelefon gesehen. Ich bezweifle jedoch, dass die Sicherheit besser ist als die von SSL. Vielleicht könnte jemand dies beweisen/widerlegen?

11
rmorero

Das Hashing auf der Serverseite ist wichtig, wie alle anderen Antworten gezeigt haben, aber ich möchte hinzufügen, dass das Hashing auf der Clientseite eine nette Sicherheitsfunktion ist zusätzlich zum serverseitigen Hashing.

Clientseitiges Hashing hat in den folgenden Szenarien Vorteile:

  1. Schützt das Kennwort des Benutzers, wenn der Server gefährdet ist. Das heißt, Wenn der Client nicht gefährdet ist, der Server jedoch, wenn der Client das Kennwort hasht, kann der Server weiterhin Zugriff auf das eine System erhalten, aber Sie haben das Kennwort des Benutzers geschützt, was wichtig ist, wenn er dieses Kennwort an anderer Stelle verwendet.
  2. Schützt das Kennwort des Benutzers, wenn der Benutzer glaubt, sich bei einem Server anzumelden, sich aber tatsächlich bei einem anderen anzumelden (Benutzerfehler). Wenn ich beispielsweise zwei Bankkonten habe und versehentlich eines der Passwörter meiner Bank in die Website der falschen Bank eingebe, würde diese Bank das Passwort meiner anderen Bank nicht kennen, wenn die Bank das Passwort clientseitig gehasht hat. Ich denke, es wäre eine "höfliche" Sache, clientseitig zu hashen, damit ihr Klartext-Passwort niemals über das Kabel übertragen wird.

Meistens zeigt es Respekt für das Passwort des Benutzers. Der Benutzer teilt ein Geheimnis, das möglicherweise nicht ausschließlich für Ihre Software gilt. Wenn Sie dieses Geheimnis respektieren, sollten Sie alles in Ihrer Macht stehende tun, um es zu schützen.

10
Samuel

Wenn Sie sich in einem HTTPS-Tunnel befinden, sollte das Kennwort oder der Hash vor der Ethernet-Überwachung geschützt werden.

Auf der Clientseite könnten Sie den Hash möglicherweise mit einer Sitzungs-ID salzen.
Dies könnte für böswilliges Javascript schwieriger zu simulieren sein.

2
bua

Sie können beides tun, Sie haben es auf dem Client gehasht. Wenn der Angreifer die https-Sicherheit durchläuft, kann er das Klartextkennwort nicht sehen. Hashing es dann erneut auf dem Server. Wenn der Angreifer die auf dem Server gespeicherten Passwörter erhält, kann er diese nicht einfach an den Server senden und Zugriff auf das Passwort erhalten.

1
nat that

Für das clientseitige Hashing des Passworts ist Javascript erforderlich. Einige Leute deaktivieren Javascript in ihrem Browser. Sie müssen mit diesem Szenario umgehen.

Ich habe Forensoftware gesehen, die clientseitig ein Passwort-Hashing durchführt und den Hash beim Anmelden sendet falls möglich, andernfalls wird das Passwort im Klartext gesendet. So funktioniert es in beiden Situationen.

Das eindeutige Senden des Kennworts ist kein großes Problem, wenn Sie https verwenden. Im Idealfall sollte sich Ihr Server dann weigern, Seiten in http bereitzustellen, um zu vermeiden, dass sich ein Mann im mittleren Angriff befindet. Der Grund dafür ist: Ein Angreifer könnte Ihre Verbindung zwangsweise von https auf http herabstufen und den Datenverkehr abhören (z. B. mit einem Tool wie SSL Strip).

1
Anonymous

Die akzeptierte Antwort von @ Nicole Calinoiu ist natürlich richtig, aber am Anfang vielleicht zu schwer zu verstehen.

Der Punkt ist, dass das Kennwort auf dem Server gehasht werden sollte, damit die böswillige Person die Hashes, die sie vom Server aus der Datenbank gehackt hat, nicht verwenden kann, um Zugriff auf Ihr Konto oder Ihre Daten zu erhalten.

Wie bereits gesagt, wenn Sie auf Client-Seite hashen und das Back-End dies unterstützt, wird der Hash zu Ihrem Passwort. Wenn der Hash über einen Hack gestohlen wird, hat der Hacker das Passwort.

@ Thomas Pornin Die Antwort hat auch einen sehr guten Punkt ergeben, warum Sie das Passwort auf dem Client hashen möchten. Das, was er in seiner ersten Geschichte beschreibt, kann jedoch nur ausgeführt werden, wenn das Back-End des Servers die Verarbeitung von Hash-Passwörtern unterstützt (dh das Passwort nicht hasht, wenn es bereits gehasht ist, sondern dass jemand versucht, so etwas zu unterstützen, ist höchst unwahrscheinlich ), was meiner Meinung nach die meiste Zeit nicht der Fall sein wird. Die zweite Geschichte von ihm ist sehr gut.

0
Ini