Cross-Site-Request-Forgery

aus Wikipedia, der freien Enzyklopädie

Eine Cross-Site-Request-Forgery (meist CSRF oder XSRF abgekürzt, deutsch etwa Website-übergreifende Anfragenfälschung) ist ein Angriff auf ein Computersystem, bei dem der Angreifer eine Transaktion in einer Webanwendung durchführt. Dies geschieht nicht direkt, sondern der Angreifer bedient sich dazu eines Opfers, das bei einer Webanwendung bereits angemeldet sein muss. Dem Webbrowser des Opfers wird ohne dessen Wissen eine HTTP-Anfrage untergeschoben. Der Angreifer wählt die Anfrage so, dass bei deren Aufruf die Webanwendung die vom Angreifer gewünschte Aktion ausführt.

Das Sicherheitsproblem ist auf die Zustandslosigkeit des HTTP-Protokolls zurückzuführen, da nach einmaliger Authentifizierung der Browser implizit jedes Mal seine Sitzungsdaten an den Server sendet. Trifft die Webanwendung keine Maßnahmen gegen CSRF-Angriffe, ist sie verwundbar.

Während sich CSRF auf jede Form der Datenänderung mittels HTTP-Anfrage bezieht, ist bei Session-Riding die Manipulation der Daten mittels einer gültigen Session des Opfers gemeint. Session-Riding ist ein Spezialfall von CSRF mit der Bedingung, dass der Sitzungsbezeichner mittels Basic/Digest Authentication oder Cookie transportiert wird.

Im Artikel hier wird vereinfacht vom Cookie gesprochen, wenn eine Sitzung (insbesondere ein Sitzungsbezeichner) gemeint ist. CSRF tritt jedoch nicht nur bei (HTTP-)Form-basierter, sondern auch bei Basic- bzw. Digest-Authentifizierung auf.

Geschichte

Bereits im Oktober 1988 veröffentlichte Norm Hardy ein Dokument, in dem er den Sachverhalt von Vertrauen auf Anwendungsebene diskutierte und diesen „a Confused Deputy“ (dt. etwa „einen verwirrten Stellvertreter“) nannte. Im Jahr 2000 wurde auf der Sicherheits-Mailingliste Bugtraq erörtert, wie ZOPE von einem confused-deputy-Problem betroffen war, welches man heute als CSRF-Sicherheitslücke einstufen würde. Später dann, im Jahr 2001, veröffentlichte Peter Watkins auf Bugtraq einen Beitrag[1] zur Diskussion „The Dangers of Allowing Users to Post Images“ (dt. etwa „Gefahren, wenn Anwender Bilder einbinden dürfen“), mit der er den Ausdruck „Cross-Site-Request-Forgery“ prägte.

Beispiele

Ein recht harmloses Beispiel einer CSRF wäre ein Link auf der Webseite des Angreifers zu der Abmelden-Funktion auf der Wikipedia:

http://de.wikipedia.org/w/index.php?title=Spezial:Userlogout

Wird einem in der Wikipedia angemeldeten Benutzer dieser Link untergeschoben, sodass sein Browser diese Anfrage absetzt, wird er ohne eigenes Zutun von der Wikipedia abgemeldet, vorausgesetzt die Webanwendung auf Wikipedia hat keinen Schutz gegen CSRF-Angriffe.

Schwerwiegender wäre eine solche URL bei der Benutzerverwaltung einer nicht öffentlichen Seite. Zum Beispiel könnte der Angreifer mit

http://www.example.com/admin.php?action=new_user&name=baduser&password=geheim

einen neuen Benutzer anlegen und sich somit unberechtigten Zugang zu der entsprechenden Webanwendung verschaffen, wenn er es schafft, dem Administrator der Webanwendung diese HTTP-Anfrage unterzuschieben und dieser angemeldet ist.

Angriffsvektoren

Damit der Angreifer eine Cross-Site-Request-Forgery ausführen kann, muss er den Webbrowser des Opfers dazu bringen, einen oder mehrere vom Angreifer manipulierte HTTP-Anfragen auszuführen. Hierzu gibt es mehrere Angriffsvektoren:

Cross-Site-Scripting

Hierbei übermittelt der Angreifer zunächst selber entsprechend gewählten HTML-Code an die Webanwendung. Diese speichert den Code und fügt ihn späteren Anfragen anderer Benutzer an, ohne den HTML-Code zu maskieren. Diese Schwachstelle bezeichnet man als Cross-Site-Scripting (XSS). Die Cross-Site-Request-Forgery besteht darin, wie der Webbrowser des Opfers mit dem HTML-Code umgeht. Dieser besteht beispielsweise aus einem img-Tag, mit dem ein Webbrowser angewiesen wird, automatisch eine Grafik für die Seite nachzuladen. Anstelle der URL, unter der die Grafik zu finden ist, wird der Angreifer hier die manipulierte Anfrage einfügen. Sobald der Webbrowser des Opfers die URL aufruft, wird also die manipulierte Anfrage abgesendet und von der Webanwendung so verarbeitet, als wäre er vom Opfer autorisiert. Anstelle eines img-Tags mit einer manipulierten URL kann der Angreifer auch JavaScript-Code in die Seite einbauen. Damit ließe sich auch die unten beschriebene Abwehrmaßnahme eines Shared Secrets unterwandern.

Unterschieben der URL

Neben der Möglichkeit, den Aufruf der manipulierten URL über Cross-Site-Scripting zu automatisieren, kann der Angreifer auch aus einer Reihe anderer Möglichkeiten wählen, um das Opfer zum Aufruf einer manipulierten URL zu bewegen. Dabei wird die URL üblicherweise entweder per E-Mail an das Opfer übermittelt oder findet sich auf einer Webseite, die nicht einmal Teil der betroffenen Webanwendung zu sein braucht. Im Gegensatz zum Cross-Site-Scripting muss der Angreifer aber (je nach Gutgläubigkeit des Opfers mehr oder weniger) Überredungskunst einsetzen, um das Opfer zum Aufruf der URL zu bewegen, was auch als Social Engineering bezeichnet wird. Dabei kann die manipulierte URL zu Täuschungszwecken entweder mittels URL-Spoofing verfremdet sein oder durch einen Kurz-URL-Dienst verschleiert werden. Wählt der Angreifer E-Mail als Medium, kann er mittels Mail-Spoofing zusätzlich um das Vertrauen des Opfers werben, indem er sich etwa als Administrator der betroffenen Webanwendung ausgibt.

Möchte der Angreifer verhindern, dass das Opfer nach dem erfolgreichen Angriff von dem Vorgang erfährt, kann der Angreifer auch zunächst die URL einer eigenen Seite angeben, die beispielsweise ein lustiges Bild enthält. In diese Seite wird der Angreifer dann aber einen versteckten Frame einbauen, in dem dann der Aufruf der manipulierten URL stattfindet. Nutzt das Opfer ein E-Mail-Programm, das ungefragt auch in der E-Mail eingebettete Bilder über den Webbrowser aus dem Internet nachlädt, könnte man hiermit diese Angriffsmethode auch ausnutzen, ohne auf die aktive Mitwirkung des Opfers angewiesen zu sein.

All diese Methoden setzen aber voraus, dass der Benutzer bereits bei der betroffenen Webanwendung angemeldet ist, seine Zugangsdaten in einem Cookie gespeichert hat oder der Aufforderung nachkommt, sich gegenüber der Webanwendung zu authentisieren. Während letzterer Fall bei einem gesunden Maß an Menschenverstand eher unwahrscheinlich ist, stellt insbesondere die erste Situation für den Angreifer eine reelle Chance auf Erfolg dar, da viele Webanwendungen dem Anwender anbieten, seine Zugangsdaten aus Komfortgründen in dessen Webbrowser zu speichern.

Local Exploit

Hat der Angreifer die Kontrolle über den Computer des Opfers durch eine dort laufende Schadsoftware, kann er ebenfalls eine CSRF ausführen. Dazu muss die Schadsoftware lediglich den Browser anweisen, die manipulierte URL aufzurufen, was mit geringen Programmierkenntnissen keine Hürde darstellt. Die Schwierigkeit bei diesem Angriff besteht vielmehr darin, eine für den Angriff geeignete Schadsoftware auf dem Computer des Opfers zu installieren. Da dies aber nicht spezifisch für den hier geschilderten Angriff ist, soll hier auch nicht näher darauf eingegangen werden.

Abwehrmaßnahmen

Je nach Angriffsvektor ist entweder der Benutzer für clientseitige oder der Betreiber der Webanwendung für serverseitige Abwehrmaßnahmen gegen eine Cross-Site-Request-Forgery zuständig.

Serverseitig

Jede Transaktion der Webapplikation muss mit einer weiteren – dem Browser und der Webanwendung – gemeinsamen geheimen Information versehen werden.

Synchronizer Token Pattern (STP)

Bei STP wird ein sogenanntes Page-Token, meistens eine Zahl oder eine Zeichenkette, in einem Hidden-Field auf der Seite eingebunden.

<input type="hidden" name="csrftoken" value="KbyUmhTLMpYj7CD2di7JKP1P3qmLlkPt" />

Ohne weitere Lücken in der Webanwendung ist dieses Hidden-Field für den Angreifer nicht auslesbar. Insbesondere eine XSS-Schwachstelle kann jedoch den CSRF-Schutz aushebeln. Letzteres gilt selbst dann, wenn die XSS-Schwachstelle bloß in einer anderen Anwendung auf derselben Domain existiert.[2]

Wie das Feld gesetzt wird, ist abhängig vom verwendeten Framework.

Beispiel in ASP.NET MVC

In ASP.NET MVC werden alle Forms automatisch mit einem Hidden-Field mit dem Anti-CSRF-Token versehen:

@using (Html.BeginForm("ChangePassword", "Manage"))
{
    // ...
}

Alternativ lässt sich dieses auch manuell setzen:

<form action="/" method="post">
    @Html.AntiForgeryToken()
</form>

Zudem gibt es in ASP.NET Core mit Microsoft.AspNetCore.Antiforgery die Möglichkeit das Token auch global zu konfigurieren:

services.AddAntiforgery(options => {
    options.FormFieldName = "csrftoken";
    options.RequireSsl = true;
});

Die Validierung des Tokens muss auf allen MVC-Controllern bzw. Methoden erfolgen, welche eine Nebenwirkung besitzen. Hierzu dienen drei Filter, welche als Attribute auf den entsprechenden Controllern bzw. Methoden gesetzt werden können:

Attribut Funktion
[ValidateAntiForgeryToken] Validiert das CSRF-Token
[AutoValidateAntiforgeryToken] Validiert das CSRF-Token für alle HTTP-Methoden ausgenommen GET, HEAD, OPTIONS, TRACE. Hierbei müssen die entsprechenden Methoden standardkonform implementiert werden.
[IgnoreAntiforgeryToken] Keine Validierung

Filter auf den Methoden überschreiben hierbei die Filter auf den Controllern.

Cookie

Das CSRF-Token kann auch in einem Cookie gespeichert werden. Dieses wird im HTTP-Header deklariert:

Set-Cookie: Csrf-token=i8XNjC4b8KVok4uw5RftR38Wgp2BFwql; expires=Thu, 23-Jul-2017 10:25:33 GMT; Max-Age=31449600; Path=/

Das Flag httpOnly ist hierbei nicht zulässig, da das Token im Browser durch ein JavaScript-Skript verarbeitet werden muss.

Bestimmte Frameworks erzwingen eine bestimmte Benennung für das CSRF-Cookie. Beispielsweise muss das Token für das $http-Service in Angular mit XSRF-TOKEN benannt werden. Anschließend wird das Token im X-XSRF-TOKEN-HTTP-Header übermittelt.[3]

Beispiel in ASP.NET MVC

Mit Microsoft.AspNetCore.Antiforgery lässt sich das Cookie wie folgt setzen:

services.AddAntiforgery(options => {
    options.CookieName = "Csrf-Token";
    options.CookiePath = "/";
    options.CookieDomain = "example.com";
    options.RequireSsl = true;
});

HTTP-Header

Eine weitere Methode das Token zu übermitteln ist der HTTP-Header. Hierzu wird der Header X-Csrf-Token verwendet. Allerdings verwenden einige Frameworks auch vom Standard abweichende Header.

Beispiele für Frameworks mit nicht-standardisierten CSRF-Header
Header Framework
X-XSRF-TOKEN Angular
X-Requested-With jQuery
X-Requested-By Jersey
Beispiel in ASP.NET MVC

Mit Microsoft.AspNetCore.Antiforgery lässt sich das Token im HTTP-Header wie folgt setzen:

services.AddAntiforgery(options => {
    options.HeaderName = "X-Csrf-Token";
    options.RequireSsl = true;
});

Behandlung von XMLHttpRequests

Bei alten Browsern, die XMLHttpRequests von verschiedenen Origin-Domänen zulassen, müssen XMLHttpRequests abgelehnt werden, wenn die im Origin-HTTP-Header eingetragene Domäne nicht Teil der zulässigen CORS-Domänen ist.

Clientseitig

Der Benutzer einer Webanwendung muss sicherstellen, dass sein Computer frei von Schadsoftware ist. Gegen ein Programm, das im Kontext des Benutzers auf dem Client ausgeführt wird, ist jede serverseitige Abwehrmaßnahme zwecklos.

Die folgenden Hinweise sind unnötig, wenn die serverseitige Sicherheit gewährleistet ist. Da der Anwender dies aber nie sicherstellen kann, werden sie der Vollständigkeit halber mit aufgeführt:

Viele Webanwendungen, wie zum Beispiel auch die Wikipedia, bieten ihren Nutzern die Möglichkeit, dauerhaft angemeldet zu sein. Technisch wird hierbei in der Regel der in einem Cookie gespeicherte Sitzungsbezeichner am Ende einer Sitzung nicht gelöscht. Diese Komfortfunktion vergrößert aber auch die Angriffsfläche, da der Angreifer nicht mehr einen Zeitpunkt abzupassen braucht, zu dem sein Opfer an der Webanwendung angemeldet ist. Der Verzicht auf diese Funktion erhöht folglich die Hürden, die der Angreifer nehmen muss.

Möchte der Angreifer eine XSS-Lücke ausnutzen, um die Sicherheitsvorkehrung eines Shared Secrets zu umgehen, ist er darauf angewiesen, dass im Browser des Opfers JavaScript oder JScript aktiviert sind. Das Deaktivieren kann folglich ebenfalls die Angriffsfläche verringern; in der Regel nutzen aber viele Webanwendungen diese clientseitigen Skriptsprachen selber, so dass dies nicht möglich ist.

Unzulängliche Abwehrmaßnahmen

Einige Maßnahmen zur Unterbindung von CSRF-Angriffen reichen nicht aus, um einen hinreichenden Schutz zu gewährleisten. Sie sind bestenfalls dazu geeignet, die Hürde für den Angreifer etwas höher zu hängen, und wiegen den Betreiber einer Webanwendung schlimmstenfalls in Scheinsicherheit.

Nur HTTP-Post akzeptieren

Ein CSRF-Angriff kann nicht dadurch verhindert werden, dass Anfragen, die zu einer Veränderung von Daten führen, nur per HTTP-POST akzeptiert werden. Auch per HTTP-POST kann ohne weiteres eine gefälschte Anfrage abgesetzt werden. Dazu erstellt der Angreifer eine Seite, auf die er das Opfer lockt. Dort wird die manipulierte Anfrage entweder mittels einer clientseitigen Skriptsprache wie zum Beispiel JavaScript erzeugt, oder der Angreifer bringt das Opfer dazu, auf einen Button oder ein Bild zu klicken, wodurch die Anfrage abgesetzt wird. Wählt der Angreifer als Ziel (target-Parameter) des Formulars einen unsichtbaren Frame oder Inlineframe, sind auch hier die Chancen gering, dass das Opfer den Angriff bemerkt.

HTTP-Referrer-Prüfung

Die Prüfung des HTTP-Referrer-Headers bietet zwar einen gewissen Schutz vor reinen CSRF-Angriffen, da gefälschte Anfragen, die von einem Angreifer mittels Täuschung des Opfers auf einer externen Webseite ausgelöst wurden, zum Teil blockiert werden können. Die Webanwendung ist jedoch gut beraten, sich nicht auf den Schutz des Referrers zu verlassen: Viele Browser-Plugins erlauben es nämlich, Anfragen mit beliebigem Referrer abzusetzen, z. B. das weit verbreitete Adobe Flash[4] (in etwas älteren Versionen). Außerdem können Benutzer oder auch Proxy-Server aus Datenschutzgründen das Übertragen des Referrers unterbinden oder gezielt einen anderen Wert eintragen, wodurch die Web-Anwendung nicht mehr allen legitimen Anwendern offensteht (false positives). Aus Gründen der Benutzbarkeit einer Webanwendung sollte man grundsätzlich gar nicht den Referrer-Header für eine HTTP-Anfrage verwenden.

Weblinks

Einzelnachweise

  1. Peter Watkins: Cross-Site Request Forgeries (Re: The Dangers of Allowing Users to Post Images). (Nicht mehr online verfügbar.) Bugtraq, 13. Juni 2001, archiviert vom Original am 9. Juli 2012; abgerufen am 26. Juli 2012 (englisch).
  2. Christian Schneider: CSRF and Same-Origin XSS. 25. Februar 2012. Abgerufen am 13. Dezember 2014.
  3. Guarding against Cross-Site Request Forgery. In: Angular.io. Google, abgerufen am 15. Mai 2017 (englisch).
  4. Forging HTTP Request Headers with Flash ActionScript. 4. Januar 2013, abgerufen am 24. Januar 2022.