Ich versuche, das gesamte Problem mit CSRF zu verstehen und angemessene Möglichkeiten zu finden, es zu verhindern. (Ressourcen, die ich gelesen habe, verstehe und zustimme: OWASP CSRF Prevention Cheat Sheet, Fragen zu CSRF)
Wie ich es verstehe, wird die Verwundbarkeit bei CSRF durch die Annahme eingeführt, dass (aus der Sicht des Webservers) ein gültiges Sitzungscookie in einer eingehenden HTTP-Anforderung die Wünsche eines authentifizierten Benutzers widerspiegelt. Aber alle Cookies für die Ursprungsdomäne werden magisch vom Browser an die Anforderung angehängt, daher kann der Server wirklich nur daraus schließen, dass die Anforderung von einem Browser stammt, der eine authentifizierte Sitzung hat; er kann nicht weiterhin annehmen, dass der Code, der in diesem Browser ausgeführt wird, oder ob er wirklich Benutzerwünsche widerspiegelt. Der Weg, dies zu verhindern, besteht darin, zusätzliche Authentifizierungsinformationen (das "CSRF-Token") in der Anforderung zu enthalten, die auf andere Weise als die automatische Cookieverwaltung des Browsers übertragen werden. Grob gesagt authentifiziert das Sitzungscookie also den Benutzer/Browser und das CSRF-Token authentifiziert den im Browser ausgeführten Code.
Also, wenn Sie ein Sitzungscookie verwenden, um Benutzer Ihrer Webanwendung zu authentifizieren, sollten Sie auch jedem Antwort eine CSRF-Token hinzufügen und bei jeder (mutationalen) Anforderung ein entsprechendes CSRF-Token verlangen. Das CSRF-Token legt dann eine Rundreise vom Server über den Browser zurück zum Server zurück, um dem Server zu beweisen, dass die Seite, die die Anforderung stellt, vom Server genehmigt wird (sogar von diesem erstellt wird).
Kommen wir zu meiner Frage, die sich um die spezifische Transportmethode für dieses CSRF-Token bei dieser Rundreise dreht.
Es scheint üblich zu sein (z. B. in AngularJS, Django, Rails), das CSRF-Token vom Server an den Client als Cookie zu senden (dh in einem Set-Cookie-Header) und dann Javascript im Client es aus dem Cookie herauszuziehen und als separaten XSRF-TOKEN-Header an den Server zurückzuschicken.
(Eine alternative Methode ist diejenige, die z. B. von Express empfohlen wird, bei der das vom Server generierte CSRF-Token in den Antworttext über Server-seitige Vorlagenexpansion aufgenommen wird, direkt an den Code/Markup angehängt wird, der es zurück an den Server senden wird, z. B. als verstecktes Formularfeld. Dieses Beispiel ist eher eine web 1.0-artige Methode, aber würde sich gut auf ein JS-lastiges Client übertragen lassen.)
Warum ist es so üblich, Set-Cookie als den nachgelagerten Transport für das CSRF-Token zu verwenden / warum ist dies eine gute Idee? Ich stelle mir vor, dass die Autoren all dieser Frameworks ihre Optionen sorgfältig abgewogen haben und das nicht falsch gemacht haben. Aber auf den ersten Blick scheint es unsinnig zu sein, Cookies zu verwenden, um eine Designbeschränkung bei Cookies zu umgehen. Tatsächlich würden Sie, wenn Sie Cookies als Transport bei der Rundreise verwenden würden (Set-Cookie: Header nachgelagert, damit der Server dem Browser das CSRF-Token mitteilt, und Cookie: Header aufsteigend, damit der Browser es dem Server zurücksendet), die Verwundbarkeit, die Sie zu beheben versuchen, wieder einführen.
Ich sehe ein, dass die oben genannten Frameworks keine Cookies für die gesamte Rundreise des CSRF-Tokens verwenden; sie verwenden Set-Cookie nachgelagert, dann etwas anderes (z. B. einen X-CSRF-Token-Header) aufsteigend, und das schließt die Verwundbarkeit aus. Aber selbst das Verwenden von Set-Cookie als nachgelagerten Transport ist potenziell irreführend und gefährlich; der Browser wird das CSRF-Token nun an jede Anforderung anhängen, einschließlich echter bösartiger XSRF-Anforderungen; im besten Fall macht das die Anforderung größer als nötig und im schlimmsten Fall könnte ein gut gemeines, aber fehlgeleitetes Stück Servercode tatsächlich versuchen, es zu verwenden, was wirklich schlecht wäre. Und weiterhin, da der eigentliche beabsichtigte Empfänger des CSRF-Tokens JavaScript auf der Clientseite ist, kann dieses Cookie nicht mit http-only geschützt werden. Das Senden des CSRF-Tokens nachgelagert in einem Set-Cookie-Header scheint also für mich ziemlich suboptimal zu sein.