Warum funktioniert ein CSRF Token?

Falc410

Vice Admiral
Registriert
Juni 2006
Beiträge
6.599
Ich weiß wie CSRF funktioniert und, dass ein Token empfohlen wird. Habe überall noch einmal nachgelesen und etwaige Pitfalls bei der Implementierung angeschaut aber das Szenario welches ich mir überlegt habe, wird nirgendwo erwähnt (z.b. Hier https://portswigger.net/web-security/csrf ).

Ein normaler User, würde ja zuerst einen GET Request machen, dann eine Webseite mit einem Formular bekommen und den CSRF Token und dann das Formular mit dem Token als POST abschicken.

Bei einem CSRF Angriff, wird der Angreifer gleich den POST Request ausführen wollen - geht natürlich nicht. Aber warum kann der Angreifer nicht einfach zwei Requests forgen? Zuerst einen GET um das Token zu bekommen (was entweder direkt im Browser des Opfers mit gespeichert wird als Cookie oder Alternativ macht der Angreifer das per Javascript selbst wenn er eh schon den Link mit Hilfe von XSS auf einer entsprechenden Seite plaziert hat) und anschließend den 2. Request als POST mit dem zuvor gewonnen Token?

Ich sehe das CSRF Token eher als zusätzlich Hürde anstatt einer richtigen Verhinderung von CSRF Angriffen. Aber anscheinend funktioniert es ja - also wo ist der Denkfehler in meinem fiktiven Szenario bei dem der Angreifer mittels CSRF einfach zwei Requests hintereinander ausführen lässt?
 
Setze ein Capcha davor und du hast die Antwort. Ohne das Lösen kein Token und damit können Automatisierungen nicht so ohne weiteres deine 2 GETs losschicken
 
Ja CAPTCHA ist ja wieder ein zusätzliches Teil - dann ist klar, dass es nicht gehen kann. Wird aber nirgendwo erwähnt (z.B. OWASP)
 
Requests auf andere Seiten sind mittels CORS abgesichert und Cookies anderer Domains kannst du nicht auslesen. Und wenn sie httpOnly markiert wurden (Session Cookie bspw.), kommst du via JS gänzlich nicht ran.
 
Das "Token" von dem du redest ist ein Session-Cookie. Die Anmeldung passiert nicht automatisch, man muss sich aktiv authentifizieren. Es gibt mehrere Gründe, warum das nicht geht.
  • Dein Browser würde dich warnen, dass du dich an einer unsicheren Seite anmeldest - das schreckt viele Nutzer ab.
  • Dein Browser würde generell jede Art von Anfrage einfach ignorieren, wenn die "Zweitseite", also die, die angegriffen werden soll, den Zugriff von der Angreifer-Seite nicht erlaubt. Die Anfragen gehen raus, aber kommt in der Antwort keine explizite Erlaubnis, verwirft dein Browser die Antwort. Und die Antwort enthält ja erst die Cookie-Informationen. Stichworte sind SOP und CORS.

Die Möglichkeiten CSRF zu benutzen sind beschränkt. Dein Angriff muss also allein durch die Anfrage, ohne die Antwort bereits vollständig möglich sein. Es stehen auch in deinem Artikel eine Hand voll Einschränkungen drin, die ein wenig ein Gefühl dafür vermitteln, warum das funktionieren kann.

Informiere dich am besten wirklich über SOP (Same-Origin-Policy), das dürfte ordentlich Klarheit schaffen.
 
  • Gefällt mir
Reaktionen: BeBur
@SoDaTierchen Ich kenne SOP und CORS und das Token hat nichts mit dem Session-Cookie zu tun. Siehe auch meinen Link oben, da wird ja beschrieben wie man eine Webseite gegen CSRF schützt. Wir reden hier auch nicht von anmelden auf unsicheren Webseiten - ich weiß nicht was du damit sagen möchtest.

SOP hat hier auch nichts zu tun, da ich ja kein JS von einer anderen Seite nachlade und ausführen möchte. Bleiben wir bei dem Beispiel, dass ich auf einer bösartigen Seite bin, die der Angreifer komplett kontrolliert (entweder seine eigene Seite oder halt per XSS).

Aber ich denke Yuuri hat trotzdem recht. Wenn das CSRF Token im Cookie abgelegt wird (wie es z.B. bei Django der der Fall ist), dann würde ich das nicht auslesen können (zumindest bei aktuellen Browsern). Aber man sollte das Token ja so oder nicht im Cookie ablegen sondern im HTML Code mit ausliefern (siehe auch OWASP https://cheatsheetseries.owasp.org/...n_Cheat_Sheet.html#synchronizer-token-pattern ).
Beispiel von OWASP (so macht es Django auch, obwohl es zusätzlich das Token im Cookie speichert, warum auch immer):
Code:
<form action="/transfer.do" method="post">
<input type="hidden" name="CSRFToken" value="OWY4NmQwODE4ODRjN2Q2NTlhMmZlYWEwYzU1YWQwMTVhM2JmNGYxYjJiMGI4MjJjZDE1ZDZMGYwMGEwOA==">
[...]
</form>
Also wenn die Seite generiert wird, wird das Token mit in die Form plaziert. Wenn ich als Angreifer also per JS einen GET Request mache und die Antwort parse kann ich das Token doch einfach auslesen aus dem hidden Field in der Form. Der zweite Request wird dann ein POST Request mit den entsprechenden Argumenten. Warum sollte das nicht funktionieren?

Und selbst wenn es im Cookie abgelegt ist und ich es nicht auslesen kann wie @Yuuri sagt, dann würde der Browser das Cookie doch sowieso mitschicken im zweiten Request.

So beschränkt scheinen die Möglichkeiten von CSRF nicht zu sein - ist ja immer noch ein heißes Thema. Nicht ganz so wie XSS aber trotzdem...
 
Zuletzt bearbeitet:
Mh, jetzt habe ich verstanden, worauf du hinaus willst. Das Token als Cookie zu verwenden ist aber Unfug - das widerspricht dem Sinn des Tokens, da der Browser das wieder selbst einfügen würde. So ein Token wird, wie du richtig angenommen hast, korrekt im HTML versenkt.

Bei CSRF werden die Cookies nicht ausgelesen, es wird ausgenutzt, dass der Browser diese selbst übermittelt.

Falc410 schrieb:
Also wenn die Seite generiert wird, wird das Token mit in die Form plaziert. Wenn ich als Angreifer also per JS einen GET Request mache und die Antwort parse kann ich das Token doch einfach auslesen aus dem hidden Field in der Form. Der zweite Request wird dann ein POST Request mit den entsprechenden Argumenten. Warum sollte das nicht funktionieren?

Du kriegst als Angreifer die Antwort des GET-requests nicht zu sehen. Das Get-request wird gefeuert, in der Antwort ist die Angreifer-Seite nicht hinterlegt, damit wird die Antwort von Browser verworfen (siehe SOP). Im JS kommt der Code nie an, weshalb auch nichts ausgelesen werden kann.

Natürlich ist das Thema heiß, weil es eine ernste Sicherheitslücke ist. Aber sie lässt sich Recht gut vermeiden.
 
Ah ok nun verstehe ich das. Ich hatte erwartet, dass man den GET Request im Hintergrund abfeuern kann und die Antwort auslesen kann, ähnlich zu curl. Aber wenn der Browser das nicht zulässt, kommt man nicht an den HTML Code und somit das Token ran. Danke
 
  • Gefällt mir
Reaktionen: SoDaTierchen
Zurück
Oben