it-swarm.com.de

Was ist ein CSRF-Token? Was ist ihre Bedeutung und wie funktioniert sie?

Ich schreibe eine Anwendung (Django, so passiert es) und möchte nur eine Vorstellung davon haben, was eigentlich ein "CSRF-Token" ist und wie es die Daten schützt. Sind die Post-Daten nicht sicher, wenn Sie keine CSRF-Token verwenden?

543
Shawn

Cross-Site Request Forgery (CSRF) in einfachen Worten

  • Angenommen, Sie sind derzeit in Ihrem Online-Banking unter www.mybank.com angemeldet.
  • Angenommen, eine Geldüberweisung von mybank.com führt zu einer Anfrage in der (konzeptionellen) Form http://www.mybank.com/transfer?to=<SomeAccountnumber>;amount=<SomeAmount>. (Ihre Kontonummer wird nicht benötigt, da dies durch Ihre Anmeldung impliziert wird.)
  • Sie besuchen www.cute-cat-pictures.org, ohne zu wissen, dass es sich um eine schädliche Website handelt.
  • Wenn der Inhaber dieser Website die Form der obigen Anfrage kennt (einfach!) Und richtig vermutet, dass Sie bei mybank.com angemeldet sind (erfordert etwas Glück!), Könnte er eine Anfrage wie http://www.mybank.com/transfer?to=123456;amount=10000 auf seiner Seite einfügen. (wobei 123456 die Nummer ihres Cayman Islands-Kontos ist und 10000 ein Betrag ist, über den Sie sich zuvor gefreut haben besitzen).
  • Sie haben diese www.cute-cat-pictures.org -Seite abgerufen, also Ihr Browser mach diese Anfrage.
  • Ihre Bank kann diesen Ursprung der Anfrage nicht erkennen: Ihr Webbrowser sendet die Anfrage zusammen mit Ihrem Cookie www.mybank.com und es sieht absolut legitim aus. Da geht dein Geld!

Dies ist die Welt ohne CSRF-Token.

Nun zum Besseren mit CSRF-Token:

  • Die Übertragungsanforderung wird um ein drittes Argument erweitert: http://www.mybank.com/transfer?to=123456;amount=10000;token=31415926535897932384626433832795028841971.
  • Dieses Token ist eine riesige, nicht zu erratende Zufallszahl, die mybank.com auf ihrer eigenen Webseite anzeigt, wenn sie es Ihnen zur Verfügung stellt. Es ist jedes Mal anders , wenn sie eine Seite an irgendjemanden liefern.
  • Der Angreifer kann das Token nicht erraten, kann Ihren Webbrowser nicht davon überzeugen, es abzugeben (wenn der Browser ordnungsgemäß funktioniert ...), und so wird der Angreifer nicht kann eine gültige Anfrage erstellen, da Anfragen mit dem falschen Token (oder ohne Token) von www.mybank.com abgelehnt werden.

Ergebnis: Sie behalten Ihre Währungseinheiten 10000. Ich schlage vor, Sie spenden etwas davon an Wikipedia.

(Ihre Laufleistung kann variieren.)

BEARBEITEN von lesenswertem Kommentar:

Es ist zu beachten, dass das Skript von www.cute-cat-pictures.org aufgrund der HTTP-Zugriffssteuerung normalerweise keinen Zugriff auf Ihr Anti-CSRF-Token von www.mybank.com hat. Dieser Hinweis ist wichtig für einige Personen, die unangemessenerweise einen Header Access-Control-Allow-Origin: * für jede Website-Antwort senden, ohne zu wissen, wofür sie gedacht sind, nur weil sie die API nicht von einer anderen Website verwenden können.

1357
Lutz Prechelt

Ja, die Post-Daten sind sicher. Aber der Ursprung dieser Daten ist nicht. Auf diese Weise kann jemand Benutzer mit JS dazu verleiten, sich bei Ihrer Website anzumelden, während er auf der Webseite des Angreifers surft.

Um dies zu verhindern, sendet Django einen zufälligen Schlüssel sowohl in Cookie- als auch in Formulardaten. Wenn Benutzer POSTs durchführen, wird geprüft, ob zwei Schlüssel identisch sind. Wenn ein Benutzer ausgetrickst wird, kann die Website eines Drittanbieters die Cookies Ihrer Website nicht abrufen, wodurch ein Authentifizierungsfehler verursacht wird.

216

Die Site generiert ein eindeutiges Token, wenn sie die Formularseite erstellt. Dieses Token ist erforderlich, um Daten an den Server zu senden/abzurufen.

Da das Token von Ihrer Site generiert und nur bereitgestellt wird, wenn die Seite mit dem Formular generiert wird, kann eine andere Site Ihre Formulare nicht imitieren. Sie verfügt nicht über das Token und kann daher keine Beiträge auf Ihrer Site veröffentlichen.

71
tkone

Das Cloud Under-Blog bietet eine gute Erklärung für CSRF-Token.

Stellen Sie sich vor, Sie hätten eine Website wie ein vereinfachtes Twitter, das auf a.com gehostet wird. Angemeldete Benutzer können Text (einen Tweet) in ein Formular eingeben, das als POST -Anforderung an den Server gesendet und veröffentlicht wird, wenn sie auf die Schaltfläche "Senden" klicken. Auf dem Server wird der Benutzer durch ein Cookie identifiziert, das seine eindeutige Sitzungs-ID enthält, sodass Ihr Server weiß, wer den Tweet gesendet hat.

Das Formular könnte so einfach sein:

 <form action="http://a.com/Tweet" method="POST">
   <input type="text" name="Tweet">
   <input type="submit">
 </form> 

Stellen Sie sich vor, ein Bösewicht kopiert dieses Formular und fügt es auf seiner bösartigen Website ein, beispielsweise b.com. Das Formular würde immer noch funktionieren. Solange ein Benutzer bei Ihrem Twitter angemeldet ist (dh er hat ein gültiges Sitzungscookie für a.com), wird die POST -Anforderung an http://a.com/Tweet gesendet und wie gewohnt verarbeitet, wenn Der Benutzer klickt auf die Senden-Schaltfläche.

Bisher ist dies kein großes Problem, solange der Benutzer darüber informiert wird, was das Formular genau tut, aber was ist, wenn unser Bösewicht das Formular wie folgt ändert:

 <form action="https://example.com/Tweet" method="POST">
   <input type="hidden" name="Tweet" value="Buy great products at http://b.com/#iambad">
   <input type="submit" value="Click to win!">
 </form> 

Wenn nun einer Ihrer Benutzer auf der Website des Bösewichts landet und auf die Schaltfläche "Klicken, um zu gewinnen!" Klickt, wird das Formular an Ihre Website gesendet, der Benutzer wird anhand der Sitzungs-ID im Cookie korrekt identifiziert und der verborgene Tweet abgerufen veröffentlicht.

Wenn unser Bösewicht noch schlimmer wäre, würde er den unschuldigen Benutzer veranlassen, dieses Formular einzureichen, sobald er seine Webseite mit JavaScript öffnet, möglicherweise sogar vollständig versteckt in einem unsichtbaren Iframe. Dies ist im Grunde eine standortübergreifende Anforderungsfälschung.

Ein Formular kann einfach von überall nach überall gesendet werden. Im Allgemeinen ist dies ein häufiges Merkmal, aber es gibt viele weitere Fälle, in denen es wichtig ist, das Senden eines Formulars nur von der Domäne aus zuzulassen, zu der es gehört.

Noch schlimmer ist es, wenn Ihre Webanwendung nicht zwischen POST und GET-Anforderungen unterscheidet (z. B. in PHP, indem Sie $ _REQUEST anstelle von $ _POST verwenden). Tu das nicht! Änderungsanforderungen für Daten könnten so einfach wie <img src="http://a.com/tweet?tweet=This+is+really+bad"> übermittelt werden, eingebettet in eine schädliche Website oder sogar eine E-Mail.

Wie stelle ich sicher, dass ein Formular nur von meiner eigenen Website gesendet werden kann? Hier kommt das CSRF-Token ins Spiel. Ein CSRF-Token ist eine zufällige, schwer zu erratende Zeichenfolge. Auf einer Seite mit einem Formular, das Sie schützen möchten, generiert der Server eine zufällige Zeichenfolge, das CSRF-Token, fügt es dem Formular als verstecktes Feld hinzu und merkt es sich auch irgendwie, indem er es in der Sitzung speichert oder ein Cookie setzt mit dem Wert. Nun würde das Formular so aussehen:

    <form action="https://example.com/Tweet" method="POST">
      <input type="hidden" name="csrf-token" value="nc98P987bcpncYhoadjoiydc9ajDlcn">
      <input type="text" name="Tweet">
      <input type="submit">
    </form> 

Wenn der Benutzer das Formular absendet, muss der Server lediglich den Wert des Felds "csrf-token" (der Name spielt keine Rolle) mit dem vom Server gespeicherten CSRF-Token vergleichen. Wenn beide Zeichenfolgen gleich sind, verarbeitet der Server das Formular möglicherweise weiter. Andernfalls sollte der Server die Verarbeitung des Formulars sofort beenden und mit einem Fehler antworten.

Warum funktioniert das? Es gibt mehrere Gründe, warum der Bösewicht aus unserem obigen Beispiel das CSRF-Token nicht erhalten kann:

Das Kopieren des statischen Quellcodes von unserer Seite auf eine andere Website ist nutzlos, da sich der Wert des ausgeblendeten Felds mit jedem Benutzer ändert. Ohne dass die Website des Bösen den CSRF-Token des aktuellen Benutzers kennt, lehnt Ihr Server die Anforderung POST immer ab.

Da die bösartige Seite des Bösewichts vom Browser Ihres Benutzers aus einer anderen Domain (b.com statt a.com) geladen wird, hat der Bösewicht keine Chance, ein JavaScript zu codieren, das den Inhalt und damit das aktuelle CSRF-Token des Benutzers lädt deine Website. Dies liegt daran, dass Webbrowser standardmäßig keine domänenübergreifenden AJAX Anfragen zulassen.

Der Bösewicht kann auch nicht auf die von Ihrem Server festgelegten Cookies zugreifen, da die Domains nicht übereinstimmen würden.

Wann sollte ich mich vor standortübergreifender Fälschung von Anfragen schützen? Wenn Sie sicherstellen können, dass Sie GET, POST und andere Anforderungsmethoden nicht wie oben beschrieben vertauschen, sollten Sie standardmäßig alle POST Anforderungen schützen.

Sie müssen PUT- und DELETE-Anforderungen nicht schützen, da wie oben erläutert ein Standard-HTML-Formular mit diesen Methoden nicht von einem Browser gesendet werden kann.

JavaScript andererseits kann in der Tat andere Arten von Anfragen stellen, z. Wenn Sie die $ .ajax () - Funktion von jQuery verwenden, müssen die Domänen für AJAX -Anforderungen übereinstimmen, um zu funktionieren (sofern Sie Ihren Webserver nicht explizit anders konfigurieren).

Dies bedeutet, dass Sie häufig nicht einmal ein CSRF-Token zu AJAX Anforderungen hinzufügen müssen, selbst wenn es sich um POST Anforderungen handelt. Sie müssen jedoch sicherstellen, dass Sie nur die CSRF umgehen Überprüfen Sie in Ihrer Webanwendung, ob die Anforderung POST tatsächlich eine Anforderung AJAX ist. Sie können dies tun, indem Sie nach einem Header wie X-Requested-With suchen, der normalerweise AJAX Anforderungen enthält. Sie können auch einen anderen benutzerdefinierten Header festlegen und auf der Serverseite überprüfen, ob er vorhanden ist. Das ist sicher, da ein Browser keine benutzerdefinierten Header zu einer regulären HTML-Formularübermittlung hinzufügt (siehe oben). Daher hat Herr Bad Guy keine Chance, dieses Verhalten mit einem Formular zu simulieren.

Wenn Sie Zweifel an AJAX Anfragen haben, weil Sie aus irgendeinem Grund nicht nach einem Header wie X-Requested-With suchen können, übergeben Sie einfach das generierte CSRF-Token an Ihr JavaScript und fügen Sie das Token dem AJAX Anfrage. Es gibt verschiedene Möglichkeiten, dies zu tun. Fügen Sie es entweder wie ein normales HTML-Formular zur Nutzlast hinzu, oder fügen Sie der AJAX -Anforderung einen benutzerdefinierten Header hinzu. Solange Ihr Server weiß, wo er in einer eingehenden Anfrage danach suchen muss, und in der Lage ist, sie mit dem ursprünglichen Wert zu vergleichen, den er in der Sitzung oder dem Cookie gespeichert hat, werden Sie sortiert.

25
Dan

Der Grund dafür ist, sicherzustellen, dass die Anforderungen von den tatsächlichen Benutzern der Site kommen. Für die Formulare wird ein csrf-Token generiert, das an die Sitzungen des Benutzers gebunden sein muss. Es wird verwendet, um Anforderungen an den Server zu senden, auf dem das Token sie überprüft. Dies ist eine Möglichkeit zum Schutz vor csrf, eine andere Möglichkeit besteht darin, den Referrer-Header zu überprüfen.

5
gladysbixly