it-swarm.com.de

Warum CSRF-Token pro Formularanforderung aktualisieren?

In vielen Tutorials und Anleitungen sehe ich, dass ein CSRF-Token pro Anfrage aktualisiert werden sollte. Meine Frage ist, warum ich das tun muss? Ist ein einzelnes CSRF-Token pro Sitzung nicht viel einfacher, als eines pro Anforderung zu generieren und die angeforderten zu verfolgen?

Das Generieren des Tokens auf Anfragebasis scheint die Sicherheit nicht über das hinaus zu verbessern, was ein Token pro Sitzung bereits tun würde. Das einzige Argument scheint der XSS-Schutz zu sein, dies gilt jedoch nicht, da das Skript bei einer XSS-Sicherheitsanfälligkeit ohnehin neue Token auslesen könnte.

Was sind die Vorteile der Generierung neuer Token pro Anfrage?

95
Philipp Gayret

Aus den bereits diskutierten Gründen ist es nicht erforderlich, pro Anforderung ein neues Token zu generieren. Es bringt fast keinen Sicherheitsvorteil und kostet Sie in Bezug auf die Benutzerfreundlichkeit: Wenn nur ein Token gleichzeitig gültig ist, kann der Benutzer nicht normal in der Webanwendung navigieren. Wenn sie beispielsweise auf die Schaltfläche "Zurück" klicken und das Formular mit neuen Werten senden, schlägt die Übermittlung fehl und sie werden wahrscheinlich mit einer feindlichen Fehlermeldung begrüßt. Wenn sie versuchen, eine Ressource auf einer zweiten Registerkarte zu öffnen, wird die Sitzung auf einer oder beiden Registerkarten zufällig unterbrochen. Es lohnt sich normalerweise nicht, die Benutzerfreundlichkeit Ihrer Anwendung zu beeinträchtigen, um diese sinnlose Anforderung zu erfüllen.

Es gibt einen Ort, an dem es sich lohnt, ein neues CSRF-Token auszustellen: bei einem Prinzipalwechsel innerhalb einer Sitzung. Das ist vor allem beim Login. Dies dient dazu, einen Sitzungsfixierungsangriff zu verhindern, der zu einer CSRF-Angriffsmöglichkeit führt.

Beispiel: Der Angreifer greift auf die Site zu und generiert eine neue Sitzung. Sie nehmen die Sitzungs-ID und fügen sie in den Browser eines Opfers ein (z. B. durch Schreiben eines Cookies aus einer anfälligen Nachbardomäne oder mithilfe einer anderen Sicherheitsanfälligkeit wie jsessionid-URLs) und fügen das CSRF-Token in ein Formular im Browser des Opfers ein. Sie warten darauf, dass sich das Opfer mit diesem Formular anmeldet, und verwenden dann einen anderen Formularbeitrag, um das Opfer zu veranlassen, eine Aktion mit dem noch lebenden CSRF-Token auszuführen.

Um dies zu verhindern, machen Sie das CSRF-Token ungültig und stellen an den Stellen (z. B. bei der Anmeldung), an denen Sie bereits dasselbe mit der Sitzungs-ID tun, ein neues Token aus, um Angriffe zur Sitzungsfixierung zu verhindern.

111
bobince

Übersicht. Standardmäßig wird empfohlen, ein eindeutiges CSRF-Token zu verwenden, das für jede Anforderung eindeutig ist. Warum? Weil ein Token pro Anforderung gegenüber bestimmten Arten von Implementierungsfehlern etwas widerstandsfähiger ist als ein Token pro Sitzung. Dies macht Token pro Anfrage wohl zur besten Wahl für die Entwicklung neuer Webanwendungen. Außerdem wird Sie kein Sicherheitsprüfer bei der Verwendung eines CSRF-Tokens pro Anforderung belästigen.

Wenn Sie ein Webanwendungsentwickler sind, ist dies alles, was Sie wissen müssen, und Sie können hier aufhören zu lesen. Wenn Sie jedoch ein Sicherheitsexperte sind, der sich über die detaillierten Gründe für diesen Rat wundert oder sich fragt, wie groß das Risiko ist, wenn Sie ein Token pro Sitzung verwenden, lesen Sie weiter ....


etwas tiefer gehen. Die Wahrheit ist, dass, wenn Sie keine anderen Schwachstellen auf Ihrer Website haben, ein einzelnes CSRF-Token pro Sitzung in Ordnung ist. Es gibt keinen Grund, warum Sie unbedingt müssen, um pro Anforderung ein neues CSRF-Token zu generieren.

Dies wird durch die Tatsache demonstriert, dass Sie auch seriöse Sicherheitsexperten finden, die sagen, dass eine andere vernünftige Möglichkeit, sich gegen CSRF zu verteidigen, die doppelte Übermittlung von Cookies ist: Mit anderen Worten, Sie verwenden clientseitiges Javascript, das einen Hash des berechnet Sitzungscookie und fügt dies zu jeder POST -Anforderung hinzu, wobei der Hash als CSRF-Token behandelt wird. Sie können sehen, dass dies im Wesentlichen im laufenden Betrieb ein CSRF-Token generiert, das für die gesamte Sitzung gleich ist .

Natürlich kenne ich das Argument, warum manche Leute empfehlen könnten, für jede Anfrage ein neues CSRF-Token zu generieren. Sie denken, wenn Sie auch eine XSS-Sicherheitsanfälligkeit auf Ihrer Website haben, ist es bei Verwendung eines einzelnen CSRF-Tokens pro Sitzung einfach, XSS zum Wiederherstellen des CSRF-Tokens zu verwenden. Wenn Sie jedoch pro Anforderung ein neues CSRF-Token generieren, ist dies der Fall wird mehr Arbeit erfordern, um das CSRF-Token wiederherzustellen. Persönlich finde ich das kein schrecklich überzeugendes Argument. Wenn Ihre Site eine XSS-Sicherheitsanfälligkeit aufweist, können CSRF-Token auch dann wiederhergestellt werden, wenn Sie für jede Anforderung ein neues CSRF-Token generieren. Es sind nur ein paar zusätzliche Zeilen schädlichen Javascript erforderlich. In beiden Fällen ist es schwierig, die Sicherheit zu gewährleisten, wenn Sie eine XSS-Sicherheitsanfälligkeit auf Ihrer Website haben und einem ernsthaften, sachkundigen Angreifer ausgesetzt sind, unabhängig davon, wie Sie Ihre CSRF-Token generieren.

Insgesamt kann es nicht schaden, für jede Anfrage ein neues CSRF-Token zu generieren. Und vielleicht ist es besser, es so zu machen, nur um Sicherheitsprüfer von Ihrem Rücken zu bekommen. Wenn Sie jedoch bereits eine Legacy-Anwendung haben, die ein einzelnes CSRF-Token für die gesamte Sitzung verwendet, würde das Ausgeben des Geldes für die Konvertierung zur Generierung eines neuen CSRF-Tokens für jede Anforderung wahrscheinlich nicht ganz oben auf meiner Prioritätenliste stehen: Ich wette, ich könnte einige andere Verwendungszwecke für dieses Geld und die Energie der Entwickler finden, die die Sicherheit noch weiter verbessern würden.

23
D.W.

Mit XSS kann ein CSRF-Token gelesen werden, auch wenn es sich um ein einzelnes Submit-Token handelt. Dies ist ein Kinderspiel. Es ist wahrscheinlich, dass diese Empfehlung eines einzelnen Submit-Tokens von jemandem stammt, der CSRF nicht versteht.

Der einzige Grund für die Verwendung eines "Single Submit Token" besteht darin, dass Sie verhindern möchten, dass der Benutzer versehentlich zweimal auf "Submit" klickt. Eine gute Verwendung besteht darin, zu verhindern, dass der Benutzer zweimal auf "Kasse" klickt und den Kunden versehentlich zweimal belastet.

Ein CAPTCHA oder die Abfrage des aktuellen Kennworts des Benutzers kann als Anti-CSRF-Maßnahme verwendet werden, die von XSS nicht umgangen werden kann.

Ich empfehle das CSRF Prevention Cheat Sheet zu lesen.

15
rook

Wenn das Token während der gesamten Sitzung gleich ist, kann ein Angreifer möglicherweise ein Token von einer Seite verlieren und es für eine andere Aktion verwenden.

Sie können beispielsweise einen Iframe verwenden, um eine Seite zu laden, und dann das Token mithilfe einer XSS-Sicherheitsanfälligkeit extrahieren. Von dort aus können Sie dieses Token verwenden, um ein Formular zur Kennwortänderung einzureichen

Die Verwendung eines Token pro Anforderung anstelle eines sitzungsweiten Tokens macht es schwieriger, verhindert jedoch nicht CSRF. Ein Angreifer kann einfach ein XSS nutzen, um das Token von der Seite zu lesen und es dann abzufeuern. Wenn das Token jedoch global ist und nicht auf diese einzelne Seite beschränkt ist, kann ein Angreifer auf jede Seite zielen, um das Token zu stehlen. Die Verwendung separater Token für jede Anforderung erschwert dies erheblich.

6
Polynomial

Neben den anderen Antworten ist es möglicherweise ratsam, das Token auch zu aktualisieren, wenn Ihr Server für BREACH-Angriff anfällig ist.

Dies erfordert die folgenden drei Bedingungen:

  • Wird von einem Server bedient, der die Komprimierung auf HTTP-Ebene verwendet
  • Reflektieren Sie Benutzereingaben in HTTP-Antwortkörpern
  • Reflektieren Sie ein Geheimnis (z. B. ein CSRF-Token ) in HTTP-Antwortkörpern

Um BREACH zu verringern, müssten Sie das CSRF-Token in der GET-Anforderung aktualisieren, die ein Formular lädt, um alle vorherigen Token ungültig zu machen. Auf diese Weise erhält ein MITM (Man-In-The-Middle), der zusätzliche Anforderungen zum Erkennen des Tokens auf der Seite erstellt, jedes Mal ein anderes Token. Dies bedeutet, dass der reale Benutzer das Formular in einer MITM-Situation nicht senden kann.

Natürlich brauchen Sie die beiden anderen Bedingungen, um auch zu gelten. Es wäre wahrscheinlich einfacher, ein CSRF-Token pro Sitzung zu verwalten und die Komprimierung auf HTTP-Ebene für alle Seiten zu deaktivieren, die Formulare bereitstellen.

3
SilverlightFox

Es ist keine sehr bekannte Tatsache, aber ein normaler String-Vergleich ist anfällig für Timing-Angriffe ( wie dieser . Lange Rede, kurzer Sinn, normale String-Vergleichsoperationen (== oder ===) vergleicht zwei Zeichenfolgen zeichenweise von links nach rechts und gibt false zurück, sobald sie auf ein Zeichen gestoßen sind, das an einer bestimmten Position in beiden Zeichenfolgen nicht gleich ist. Dies ergibt einen winzigen Unterschied im Timing, der nachweislich nachweisbar war.

Durch die Verwendung eines Timing-Angriffs, um jeden möglichen Charakter für jede Position auszuprobieren, ist es möglich, den tatsächlichen Token herauszufinden. Durch Erstellen eines neuen Tokens bei jeder Übermittlung einer Anforderung mit einem Token kann dieser Angriff verhindert werden.

Dies funktioniert natürlich nur, wenn Sie das Token auch neu erstellen, wenn ein ungültiges Token gesendet wurde, was möglicherweise unerwünscht ist. Daher ist es besser, dies zu beheben, indem Sie eine zeitunempfindliche Zeichenfolgenvergleichsfunktion wie diese verwenden.

2
user2428118

Ein Grund für den Wunsch, das CSRF-Token pro Anforderung zu ändern, besteht darin, das Komprimierungsleck des Tokens zu verringern. Damit meine ich, dass wenn der Angreifer Eve Daten auf eine Seite einfügen kann, die das Token enthält, an das die Seite komprimiert gesendet wird, Eve das erste Zeichen der Zeichenfolge erraten kann, die einen kleineren Datensatz für die Seite erhält, und weiß, dass sie richtig geraten hat weiter zum nächsten Zeichen.

Dies ähnelt einem Timing-Angriff.

Im Moment gibt es keinen Grund (den ich kenne), das Token zu ändern, wenn es nur in den HTTP-Headern gesendet wird.

Eine andere Methode besteht darin, das Token zu ändern, sobald eine fehlgeschlagene Anforderung entdeckt wird. Dies kann jedoch zu Problemen führen, wenn der Benutzer kein Formular senden kann.

0
edruid