it-swarm.com.de

Sollte ich den CSRF-Schutz auf Rest-API-Endpunkten verwenden?

Kurzer Hinweis: Dies ist kein Duplikat von CSRF-Schutz mit benutzerdefinierten Headern (und ohne Validierung des Tokens) trotz einiger Überlappungen. In diesem Beitrag wird erläutert, wie der CSRF-Schutz auf Rest-Endpunkten durchgeführt wird, ohne dass erläutert wird, ob dies tatsächlich erforderlich ist. In der Tat sprechen viele CSRF/Rest-Fragen, die ich auf dieser Website gelesen habe, über das Sichern der Endpunkte über CSRF-Token, ohne tatsächlich zu diskutieren, ob dies erforderlich ist oder nicht. Daher diese Frage.

Ist CSRF-Schutz für Rest-API-Endpunkte erforderlich?

Ich habe viele Diskussionen über das Sichern von REST Endpunkten gegen CSRF-Angriffe gesehen, aber nachdem ich mir viele Gedanken über das Thema gemacht habe, bin ich mir sehr sicher, dass CSRF-Token auf einem REST Endpunkt Null gewähren zusätzlicher Schutz. Wenn Sie den CSRF-Schutz auf einem REST Endpunkt aktivieren, wird Ihrer Anwendung lediglich nutzloser Code hinzugefügt, und ich denke, dieser sollte übersprungen werden. Möglicherweise fehlt mir jedoch etwas, daher diese Frage. Ich denke, es wird helfen, sich vor Augen zu halten, warum CSRF-Schutz überhaupt notwendig ist und vor welchen Angriffsvektoren es schützt:

Warum CSRF?

Es läuft wirklich darauf hinaus, dass der Browser automatisch Anmeldeinformationen für jede Anfrage anzeigt, indem er Cookies mitsendet. Wenn eine Sitzungs-ID in einem Cookie gespeichert ist, sendet der Browser diese automatisch zusammen mit allen Anfragen, die zur ursprünglichen Website zurückkehren. Dies bedeutet, dass ein Angreifer die Authentifizierungsdetails nicht kennen muss, um als Benutzer des Opfers eine Aktion ausführen zu können. Vielmehr muss der Angreifer lediglich den Browser des Opfers dazu verleiten, eine Anfrage zu stellen, und die Anmeldeinformationen zur Authentifizierung der Anfrage werden kostenlos mitgeliefert.

Geben Sie eine REST API ein

Rest-API-Endpunkte unterscheiden sich sehr stark von anderen Anforderungen: Sie sind spezifisch zustandslos und sollten niemals Daten aus einem Cookie oder einer Sitzung akzeptieren/verwenden. Infolgedessen ist eine REST API, die sich an den Standard hält, automatisch gegen einen solchen Angriff immun. Selbst wenn ein Cookie vom Browser gesendet wurde, werden alle mit dem Cookie verknüpften Anmeldeinformationen vollständig ignoriert. Die Authentifizierung von Aufrufen einer REST API erfolgt auf völlig andere Weise. Die gebräuchlichste Lösung besteht darin, eine Art Authentifizierungsschlüssel (ein OAuth Token oder dergleichen) zu haben, der irgendwo im Header oder möglicherweise im Anforderungshauptteil selbst gesendet wird.

Da die Authentifizierung anwendungsspezifisch ist und der Browser selbst nicht weiß, was das Authentifizierungstoken ist, kann ein Browser keine Authentifizierungsdaten automatisch bereitstellen, selbst wenn er irgendwie dazu verleitet wird, den API-Endpunkt zu besuchen. Infolgedessen ist ein Cookie-freier REST Endpunkt vollständig immun gegen CSRF-Angriffe.

Oder fehlt mir etwas?

145
Conor Mancone

Ursprünglich wollte ich keine Selbstantwort, aber nach mehr Lesen habe ich eine meiner Meinung nach umfassende Antwort gefunden, die auch erklärt, warum einige möglicherweise immer noch am CSRF-Schutz für REST interessiert sind. Endpunkte.

Keine Cookies = Keine CSRF

So einfach ist das wirklich. Browser senden Cookies zusammen mit allen Anfragen. CSRF-Angriffe hängen von diesem Verhalten ab. Wenn Sie keine Cookies verwenden und sich bei der Authentifizierung nicht auf Cookies verlassen, gibt es absolut keinen Raum für CSRF-Angriffe und keinen Grund, einen CSRF-Schutz einzurichten. Wenn Sie Cookies haben, insbesondere wenn Sie diese zur Authentifizierung verwenden, benötigen Sie CSRF-Schutz. Wenn Sie nur wissen möchten, ob ich einen CSRF-Schutz für meinen API-Endpunkt benötige? Sie können hier anhalten und mit Ihrer Antwort gehen. Ansonsten steckt der Teufel im Detail.

h/t bis paj28: Während Cookies der primäre Angriffsvektor für CSRF-Angriffe sind, sind Sie auch anfällig, wenn Sie die HTTP/Basic-Authentifizierung verwenden. Im Allgemeinen ist CSRF wichtig, wenn der Browser Anmeldeinformationen für Ihre App automatisch weitergeben kann. Nach meiner Erfahrung sind Cookies die am häufigsten verwendete Technologie, um CSRF zu ermöglichen. Es werden jedoch auch einige andere Authentifizierungsmethoden verwendet, die zu derselben Sicherheitsanfälligkeit führen können.

REST = Stateless

Wenn Sie jemanden fragen, was REST ist, erhalten Sie verschiedene Antworten, in denen verschiedene Eigenschaften besprochen werden. Sie können so viel sehen, weil jemand diese Frage zum Stapelüberlauf gestellt hat: https://stackoverflow.com/questions/671118/what-exactly-is-restful-programming

Eine Eigenschaft von REST, auf die ich mich immer verlassen habe, ist, dass es zustandslos ist. Die Anwendung selbst hat natürlich Stand. Wenn Sie keine Daten irgendwo in einer Datenbank speichern können, ist Ihre Anwendung ziemlich eingeschränkt. In diesem Fall hat zustandslos jedoch eine sehr spezifische und wichtige Bedeutung: REST Anwendungen verfolgen den Status für die Anwendung clientseitig nicht. Wenn Sie Sitzungen verwenden, behalten Sie (mit ziemlicher Sicherheit) den clientseitigen Status im Auge und sind keine REST-vollständige Anwendung. Eine Anwendung, die Sitzungen (insbesondere für Anmeldungen) verwendet, die über Cookies verfolgt werden, ist also keine REST-vollständige Anwendung (IMO) und sicherlich anfällig für CSRF-Angriffe, selbst wenn sie ansonsten wie eine REST -Anwendung aussieht .

Ich denke, es ist eine kurze Anmerkung wert, dass ein Grund dafür, dass clientseitige Statuslosigkeit für REST Anwendungen wichtig ist, darin besteht, dass die Fähigkeit von Vermittlern, Antworten zwischenzuspeichern, auch ein wünschenswerter Teil des REST ist Paradigma. Solange die Anwendung den clientseitigen Status verfolgt, ist kein Caching möglich.

Rest ≠ Cookieless

Aus diesen Gründen ging ich zunächst davon aus, dass eine vollständig kompatible REST -Anwendung niemals Sitzungen, niemals Cookies und daher niemals CSRF-Sicherheit benötigen würde. Es gibt jedoch mindestens einen Anwendungsfall, der Cookies ohnehin bevorzugt: dauerhafte Anmeldungen.

Stellen Sie sich eine typische clientseitige (in diesem Fall Browser, nicht mobile) Webanwendung vor. Sie beginnen mit der Anmeldung, die eine REST API zum Überprüfen der Benutzeranmeldeinformationen verwendet und im Gegenzug ein Token zum Autorisieren zukünftiger Anforderungen erhält. Bei Anwendungen mit nur einer Seite können Sie dieses Token einfach im Speicher behalten. Dadurch wird der Benutzer jedoch effektiv abgemeldet, wenn er die Seite schließt. Infolgedessen wäre es gut, den Status an einem Ort beizubehalten, der länger als eine einzelne Browsersitzung dauern kann. Lokaler Speicher ist eine Option, aber auch anfällig für XSS-Angriffe: Ein erfolgreicher XSS-Angriff kann dazu führen, dass der Angreifer Ihre Anmeldetoken greift und sie an den Angreifer sendet, um sie nach eigenem Ermessen zu verwenden.

Aus diesem Grund habe ich einige Vorschläge gesehen, Cookies zum Speichern von Anmeldetoken zu verwenden. Mit einem Cookie können Sie das Nur-http-Flag setzen, wodurch verhindert wird, dass die Anwendung das Cookie nach dem Setzen liest. Infolgedessen kann der Angreifer im Falle eines XSS-Angriffs weiterhin Anrufe in Ihrem Namen tätigen, jedoch nicht alle zusammen mit dem Autorisierungstoken davonkommen. Diese Verwendung von Cookies verstößt nicht direkt gegen die Statuslosigkeit von REST, da der Server den clientseitigen Status immer noch nicht verfolgt. Es wird nur nach Authentifizierungsdaten in einem Cookie gesucht und nicht nach dem Header.

Ich erwähne dies, weil es möglicherweise ein legitimer Grund ist, Cookies mit einer REST API zu verwenden, obwohl es offensichtlich an einer bestimmten Anwendung liegt, die verschiedenen Sicherheits- und Usability-Bedenken auszugleichen. Ich persönlich würde versuchen, die Verwendung von Cookies mit REST APIs zu vermeiden, aber es kann durchaus Gründe geben, sie trotzdem zu verwenden. In beiden Fällen ist die allgemeine Antwort einfach: Wenn Sie Cookies (oder andere Authentifizierungsmethoden, die der Browser automatisch ausführen kann) verwenden, benötigen Sie einen CSRF-Schutz. Wenn Sie keine Cookies verwenden, tun Sie dies nicht.

152
Conor Mancone

"Es gibt keine Möglichkeit für einen Browser, automatisch Authentifizierungsdaten bereitzustellen, selbst wenn er irgendwie dazu verleitet wird, den API-Endpunkt zu besuchen."

Seien Sie in privaten Netzwerken mit integrierter Windows/Kerberos-Authentifizierung vorsichtig. In diesem Szenario stellt der Brower automatisch Anmeldeinformationen (Kerberos oder NTLM-Token) bereit, wenn er dafür konfiguriert ist.

Also - ich glaube in diesem Fall ist CSRF erforderlich.

7
stuartm9999

Ob ein CSRF-Schutz erforderlich ist oder nicht, hängt von zwei Faktoren ab:

Führt die Anforderung eine Aktion zum Ändern des Status aus (nicht dasselbe wie REST API Statelessness) - Aktionen zum Ändern des Status sind alle Aktionen, die den Status der Anwendung ändern. Zum Beispiel etwas löschen, etwas hinzufügen, etwas aktualisieren. Dies sind Aktionen, mit denen die Anwendung den gesicherten Status des Benutzers ändert. Alle Post-Anfragen und einige Get-Anfragen fallen unter diese Kategorie. REST = APIs können Statusänderungsaktionen haben.

Wird die Authentifizierung vom Browser bereitgestellt (nicht auf Cookies beschränkt) - CSRF tritt auf, weil Authentifizierungsinformationen in der Anforderung des Browsers enthalten sind, unabhängig davon, ob die Anforderung vom Benutzer oder einer anderen geöffneten Registerkarte gestartet wurde. Daher benötigt jede Art von Authentifizierung, bei der der Browser Informationen selbst einschließen kann, einen CSRF-Schutz. Dies umfasst sowohl Cookie-basierte Sitzungen als auch die grundlegende Authentifizierung.

Für alle Anfragen, die in die oben genannten 2 Kategorien fallen, ist CSRF-Schutz erforderlich.

6
an0904

Rest-API-Endpunkte unterscheiden sich sehr stark von anderen Anforderungen: Sie sind spezifisch zustandslos und sollten niemals Daten aus einem Cookie oder einer Sitzung akzeptieren/verwenden.

Wenn Sie auf diese Weise "REST-API" definieren, ist kein CSRF möglich. CSRF, auch "Session Riding" genannt [ Zitat ], funktioniert offensichtlich nicht, wenn es keine Session zum "Reiten" gibt.

4
John Wu

Eine Sache, die ich zu den anderen Antworten hinzufügen möchte, ist, dass CSRF-Schutz notwendig ist nur in der Domäne und im Pfad des Cookies fraglich. Oder anders ausgedrückt:

Autorisierung! = Authentifizierung
Cookies == Authentifizierung
Token == Autorisierung

Dies ist relevant für die Implementierung dauerhafter Anmeldungen (Ihr 3. Punkt). Wenn Sie Ihre Cookies an login.example.com Anbringen, auf dem sich Ihre Anmelde-Benutzeroberfläche und Ihr /authorize Endpunkt befinden, können Sie alle paar Minuten einen impliziten OAuth Flow) ausführen, ohne dass dies erforderlich ist ein neues Login (zB kein Passwortdialog). Der Client kann das so erworbene Zugriffstoken ohne CSRF an api.example.com senden, da keine Cookies an diesen Host gesendet werden.

So können Sie immer noch sicher vermeiden, mit CSRF auf Ihren REST APIs) umzugehen. Ihr Anmelde-/Authentifizierungsserver ist jedoch besser kugelsicher (und CSRF-geschützt).

3
Charlie Reitzel

Antwort : Wenn Sie das Token im localStorage speichern und mit JS an Ihre Anforderungen anhängen, wird automatisch der CSRF-Schutz garantiert (aufgrund der Art des Angriffs) )

Nachtrag : Ob es sicherer ist, nur http-Cookies anstelle von localStorage zu verwenden (so scheint es, als würde diese Art des CSRF-Schutzes eine Problem bei XSS): ist es eigentlich nicht. Dies würde es dem Angreifer, der über ein ausgenutztes XSS die Kontrolle über JS auf Ihrer Site hat, nur ein wenig erschweren. @bobince hat das mit besseren Worten erklärt: Verhindert das Setzen von httponly das Stehlen einer Sitzung mit XSS?

XSS ist eine Sicherheitsanfälligkeit auf Anwendungsebene. Ihre Auswirkungen können jedoch gemindert werden, indem die Leistung des Tokens durch die Verwendung von Ansprüchen begrenzt wird (Beschränkung auf das erforderliche Minimum).

0
Raywell