it-swarm.com.de

Wie sende ich ein Passwort sicher über HTTP?

Wenn ein Benutzer auf einem Anmeldebildschirm ein Formular mit seinem Benutzernamen und seinem Kennwort sendet, wird das Kennwort im Klartext gesendet (auch mit POST, korrigieren Sie mich, wenn ich falsch liege).

Die Frage ist also, wie der Benutzer und sein Passwort vor dem Zugriff Dritter geschützt werden können, die möglicherweise die Kommunikationsdaten abhören.

Ich bin mir bewusst, dass HTTPS eine Lösung für das Problem darstellt, aber gibt es eine Möglichkeit, mithilfe des Standard-HTTP-Protokolls (POST-Anforderung) zumindest ein gewisses Maß an Sicherheit zu gewährleisten? (vielleicht in irgendeiner Weise mit Javascript)

EDIT Ich habe möglicherweise einige wichtige Dinge ausgelassen.

Es ging um eine Seite - das ist eine PHP generierte Anmeldeseite, die natürlich in einer HTTP GET-Anfrage als HTML-Datei an den Benutzer gesendet wird. Es wurde keine (@ Jeremy Powel) -Verbindung hergestellt Ich möchte, dass der gesamte Prozess für den Benutzer transparent ist - er möchte ein Kennwort übermitteln und sich nicht mit Kryptografie befassen.

Vielen Dank.

110
Kornelije Petak

Die Verwendung von HTTP mit SSL vereinfacht Ihr Leben erheblich und Sie können sich entspannt zurücklehnen. Sehr kluge Leute (zumindest schlauer als ich!) Haben diese Methode der vertraulichen Kommunikation jahrelang unter die Lupe genommen.

61
Jeremy Powell

Sichere Authentifizierung ist ein weites Thema. Kurz gesagt, wie @ jeremy-powell bereits sagte, bevorzugen Sie immer das Senden von Anmeldeinformationen über HTTPS anstelle von HTTP. Es wird eine Menge sicherheitsrelevanter Kopfschmerzen beseitigen.

TSL/SSL-Zertifikate sind heutzutage recht günstig. In der Tat, wenn Sie kein Geld ausgeben möchten, gibt es eine kostenlose letsencrypt.org - automatisierte Zertifizierungsstelle.

Sie können noch einen Schritt weiter gehen und caddyserver.com verwenden, das letsencrypt im Hintergrund aufruft.

Sobald wir HTTPS aus dem Weg geräumt haben ...

Sie sollten Login und Passwort nicht über POST Payload- oder GET-Parameter senden. Verwenden Sie stattdessen einen Authorization-Header (Basic Access Authentication Schema), der wie folgt aufgebaut ist:

  • Der Benutzername und das Passwort werden in einer durch einen Doppelpunkt getrennten Zeichenfolge zusammengefasst, z. B .: Benutzername: Passwort
  • Die resultierende Zeichenfolge wird mit der RFC2045-MIME-Variante von Base64 codiert, mit Ausnahme von 76 Zeichen/Zeile.
  • Das Autorisierungsverfahren und ein Leerzeichen, d. H. "Basic", werden dann vor die codierte Zeichenfolge gesetzt.

quelle: Wikipedia: Authorization header

Es mag ein bisschen kompliziert erscheinen, ist es aber nicht. Es gibt viele gute Bibliotheken, die diese Funktionalität sofort für Sie bereitstellen.

Es gibt einige gute Gründe, warum Sie einen Authorization-Header verwenden sollten

  1. Es ist ein Standard
  2. Es ist einfach (nachdem Sie gelernt haben, wie man sie benutzt)
  3. Sie können sich auf der URL-Ebene wie folgt anmelden: https://user:[email protected]/login (Chrome konvertiert sie beispielsweise automatisch in den Authorization -Header.)

WICHTIG:
Wie von @zaph in seinem Kommentar unten ausgeführt, ist das Senden vertraulicher Informationen als GET-Abfrage keine gute Idee, da sie höchstwahrscheinlich in Serverprotokollen enden werden.

enter image description here

29
FullStackForger

Sie können ein Challenge-Response-Schema verwenden. Sagen wir, der Client und der Server kennen beide ein Geheimnis S. Dann kann der Server sicher sein, dass der Client das Passwort kennt (ohne es preiszugeben), indem er:

  1. Der Server sendet eine Zufallszahl R an den Client.
  2. Der Client sendet H (R, S) zurück an den Server (wobei H eine kryptografische Hash-Funktion wie SHA-256 ist).
  3. Der Server berechnet H (R, S) und vergleicht es mit der Antwort des Clients. Wenn sie übereinstimmen, weiß der Server, dass der Client das Kennwort kennt.

Edit:

Hier gibt es ein Problem mit der Aktualität von R und der Tatsache, dass HTTP zustandslos ist. Dies kann erledigt werden, indem der Server ein Geheimnis erstellt. Nenne es Q, das nur der Server kennt . Dann sieht das Protokoll so aus:

  1. Der Server generiert die Zufallszahl R. Er sendet sie dann an den Client H (R, Q) (die vom Client nicht gefälscht werden kann).
  2. Der Client sendet R, H (R, Q) und berechnet H (R, S) und sendet alles zurück an den Server (wobei H eine kryptografische Hash-Funktion wie SHA-256 ist).
  3. Der Server berechnet H (R, S) und vergleicht es mit der Antwort des Clients. Dann nimmt es R und berechnet (erneut) H (R, Q). Wenn die Client-Version von H (R, Q) und H (R, S) mit der Neuberechnung des Servers übereinstimmt, betrachtet der Server den Client als authentifiziert.

Da H (R, Q) vom Client nicht gefälscht werden kann, fungiert H (R, Q) als Cookie (und könnte daher tatsächlich als Cookie implementiert werden).

Noch eine Änderung:

Die vorherige Bearbeitung des Protokolls ist falsch, da jeder, der H (R, Q) beobachtet hat, es mit dem richtigen Hash wiederzugeben scheint. Der Server muss sich merken, welche Rs nicht mehr aktuell sind. Ich beantworte diese Frage mit CW'ing, damit ihr das ändern und etwas Gutes ausarbeiten könnt.

14
Jeremy Powell

Wenn Ihr Webhost dies zulässt oder Sie mit vertraulichen Daten umgehen müssen, verwenden Sie HTTPS (Punkt). (Es ist oft gesetzlich vorgeschrieben).

Ansonsten wenn du etwas über HTTP machen willst. Ich würde so etwas machen.

  1. Der Server bettet seinen öffentlichen Schlüssel in die Anmeldeseite ein.
  2. Der Client füllt das Anmeldeformular aus und klickt auf Senden.
  3. Eine AJAX Anfrage ruft den aktuellen Zeitstempel vom Server ab.
  4. Clientseitiges Skript verkettet die Anmeldeinformationen, den Zeitstempel und ein Salt (gehasht aus analogen Daten, z. B. Mausbewegungen, Tastendruckereignissen) und verschlüsselt sie mit dem öffentlichen Schlüssel.
  5. Sendet den resultierenden Hash.
  6. Server entschlüsselt den Hash
  7. Überprüft, ob der Zeitstempel aktuell genug ist (lässt nur ein kurzes Fenster von 5 bis 10 Sekunden zu). Lehnt die Anmeldung ab, wenn der Zeitstempel zu alt ist.
  8. Speichert den Hash für 20 Sekunden. Lehnt denselben Hash für die Anmeldung während dieses Intervalls ab.
  9. Authentifiziert den Benutzer.

Auf diese Weise ist das Passwort geschützt und der gleiche Authentifizierungs-Hash kann nicht wiederholt werden.

Informationen zur Sicherheit des Sitzungstokens Das ist etwas schwieriger. Es ist jedoch möglich, die Wiederverwendung eines gestohlenen Sitzungstokens etwas zu erschweren.

  1. Der Server legt ein zusätzliches Sitzungscookie fest, das eine zufällige Zeichenfolge enthält.
  2. Der Browser sendet dieses Cookie bei der nächsten Anfrage zurück.
  3. Der Server überprüft den Wert im Cookie. Wenn er anders ist, wird die Sitzung abgebrochen. Andernfalls ist alles in Ordnung.
  4. Der Server setzt das Cookie erneut mit einem anderen Text.

Wenn also das Sitzungstoken gestohlen wurde und eine Anforderung von einer anderen Person gesendet wird, wird die Sitzung bei der nächsten Anforderung des ursprünglichen Benutzers zerstört. Wenn der Benutzer aktiv auf der Website surft und häufig auf Links klickt, kommt der Dieb mit dem gestohlenen Token nicht weit. Dieses Schema kann verstärkt werden, indem für die vertraulichen Vorgänge eine andere Authentifizierung erforderlich ist (z. B. das Löschen eines Kontos).

BEARBEITEN: Beachten Sie, dass dies MITM-Angriffe nicht verhindert, wenn der Angreifer eine eigene Seite mit einem anderen öffentlichen Schlüssel erstellt und Anforderungen an den Server weiterleitet. Zum Schutz muss der öffentliche Schlüssel im lokalen Speicher des Browsers oder in der App gespeichert werden, um solche Tricks zu erkennen.

Über die Implementierung: RSA ist wahrscheinlich der bekannteste Algorithmus, aber für lange Schlüssel ist es ziemlich langsam. Ich weiß nicht, wie schnell eine PHP oder Javascript-Implementierung sein würde. Aber wahrscheinlich gibt es schnellere Algorithmen.

10
Calmarius

Ich würde ein serverseitiges und clientseitiges Diffie-Hellman-Schlüsselaustauschsystem mit AJAX oder mehreren Formularvorlagen (ich empfehle die erstere) verwenden, obwohl ich keine guten Implementierungen davon sehe Denken Sie daran, dass eine JS-Bibliothek immer von MITM beschädigt oder geändert werden kann.

4
Andrey Akhmetov

Sie können SRP verwenden, um sichere Kennwörter über einen unsicheren Kanal zu verwenden. Der Vorteil ist, dass ein Angreifer die Passwörter auch dann nicht auf einem anderen Server verwenden kann, wenn er den Datenverkehr abfängt oder den Server kompromittiert. https://github.com/alax/jsrp ist eine Javascript-Bibliothek, die sichere Passwörter über HTTP im Browser oder serverseitig (über Knoten) unterstützt.

3
Brian Minton

HTTPS ist so leistungsfähig, weil es asymmetrische Kryptografie verwendet. Mit dieser Art der Kryptografie können Sie nicht nur einen verschlüsselten Tunnel erstellen, sondern auch sicherstellen, dass Sie mit der richtigen Person und nicht mit einem Hacker sprechen.

Hier ist Java Quellcode, der die asymmetrische Verschlüsselung RSA (von PGP verwendet) verwendet, um zu kommunizieren: http://www.hushmail.com/services/downloads/

1
rook

sie können ssl für Ihren Host verwenden. Es gibt ein kostenloses Projekt für ssl wie letsencrypt https://letsencrypt.org/

0
mk990