© saicle/Shutterstock.com
Neues rund um eine sehr alte Schwachstelle: Cross-Site Request Forgery

Confused Deputy 2015


Cross-Site Request Forgery (CSRF) ist eine sehr alte Schwachstelle. Das zugrunde liegende Problem wurde erstmals 1988 unter dem Namen „Confused Deputy“ beschrieben, die Bezeichnung „Cross-Site Request Forgery“ wurde 2001 geprägt. Inzwischen schreiben wir das Jahr 2015, und CSRF ist immer noch aktuell. Wäre es nicht Zeit, diese Schwachstelle endlich loszuwerden?

Beim Cross-Site Request Forgery wird das Vertrauen einer Webanwendung in den Benutzer ausgenutzt, indem bestimmte Aktionen durch den Aufruf eines URLs ausgelöst und dabei im Kontext des eingeloggten Benutzers ausgeführt werden. Er wird von der Webanwendung meist anhand eines Session-Cookies erkannt, der vom Browser automatisch mit jedem Request an den betreffenden Server mitgeschickt wird.

Bei einem CSRF-Angriff wird das Opfer dazu gebracht, einen präparierten HTTP-Request abzuschicken, der dann eine Aktion in seinem Namen ausführt.

Ein einfaches Beispiel

Ein einfaches Beispiel für einen CSRF-Angriff loggt einen Benutzer bei der Webanwendung aus, wenn er eine Seite mit einem präparierten img-Tag darin aufruft. Das Ausloggen erfolgt zum Beispiel über den Aufruf von http://www.anwendung.example/logout.php; der CSRF-Angriff besteht dann aus einem img-Tag mit entsprechendem „Bild“-URL, zum Beispiel <img src="http://www.anwendung.example/logout.php"> auf einer Webseite, auf die der Benutzer gelockt wird. Dabei ist es völlig egal, wo diese Seite gehostet wird, sie muss nicht einmal auf www.anwendung.example liegen.

Sobald das Opfer diese präparierte Seite erreicht, wird sie vom Browser gerendert. Wird dabei das img-Tag erreicht, versucht der Browser das „Bild“ zu laden und sendet dabei den Request zum Ausloggen des Benutzers an die Webanwendung. Dass diese kein Bild zurückliefert, stört dabei nicht weiter. Selbst wenn der Benutzer sich über die Markierung für ein fehlendes Bild in der fertigen Seite wundert, ist es für eine Reaktion längst zu spät. Die angegriffene Webanwendung hat den Request bereits erhalten, den Benutzer anhand seines Session-Cookies erkannt und ausgeloggt.

Nun ist das Ausloggen eines Benutzers nicht mal als schlechter Scherz geeignet; er meldet sich einfach wieder an und die Sache ist erledigt. Es sind aber auch sehr viel folgenreichere Angriffe möglich. Prinzipiell lässt sich fast jede Funktion einer Webanwendung über CSRF missbrauchen, sofern sie nicht vor entsprechenden Angriffen geschützt ist.

Ein uraltes Problem, aber nicht totzukriegen

Die Probleme, die sich durch das Vertrauen einer Anwendung in einen Benutzer ergeben, wurden erstmals 1988 unter dem Namen „Confused Deputy“ von Norm Hardy beschrieben [1]. Der Begriff Cross-Site Request Forgery wurde 2001 von Peter Watkins geprägt, der auch den Namen „Sea Surf“ für die Abkürzung CSRF vorschlug [2]. Trotz ihres Alters sind CSRF-Schwachstellen immer noch ein großes Problem, wie zum Beispiel ein Blick in die entsprechende Kategorie von Packet Storm Security zeigt [3].

Ein Beispiel für die Gefahren, die durch eine CSRF-­Schwachstelle entstehen können, sind einige CSRF-Schwachstellen in den Domaineinstellungen des Registrars GoDaddy [4]. Sie hätten es einem Angreifer erlaubt, zum Beispiel die Namensserver einer Domain zu ändern oder die automatische Erneuerung der Registrierung auszuschalten. Beides hätte ein Cyberkrimineller ausnutzen können, um eine bei GoDaddy registrierte Domain zu übernehmen. Er hätte nur den für die gewünschte Domain verantwortlichen Admin auf eine entsprechend präparierte Webseite locken müssen, was ja nun wirklich keine Kunst ist. In diesem Fall dürfte dazu zum Beispiel schon eine E-Mail reichen, in der der Admin darüber informiert wird, dass es eine Reihe von Beschwerden über seine Domain gibt. Sie werden auf der Webseite mit dem CSRF-Angriff beschrieben. Wenn der Admin sich dann die Beschwerden ansehen will und währenddessen bei GoDaddy eingeloggt ist, ist der CSRF-­Angriff erfolgreich.

Altbekannter Schutz auf Client und Server

Damit sind wir ganz nebenbei schon beim clientseitigen Schutz vor CSRF-Angriffen angelangt: Loggen Sie sich immer aus, wenn Sie eine Webanwendung verlassen. Wenn Sie nicht angemeldet sind, laufen CSRF-Angriffe ins Leere, denn die benötigen eine aktive Session, die sie missbrauchen können. CSRF wird darum manchmal auch „Session Riding“ genannt.

Serverseitig schützt man die Funktionen durch zufällig erzeugte Token, die in der Session gespeichert und als zusätzlicher Parameter mit jedem zu schützenden Request mitgeschickt werden. Das Token kann dazu zum Beispiel als unsichtbarer Parameter in den Formularen oder als zusätzlicher Parameter in Links auf der Seite gespeichert werden. Empfängt der Server einen mit einem Token geschützten Request ohne gültiges Token, handelt es sich um einen CSRF-Angriff, und der Request darf nicht ausgeführt werden.

Dieser Schutz funktioniert, weil der Angreifer den CSRF-Angriff vorab komplett vorbereiten muss und ihn vom Benutzer nur abschicken lassen kann. Da er das nicht vorhersagbare Token bei der Vorbereitung des Angriffs nicht kennt, kann er es auch nicht in den CSRF-Request integrieren, sodass der Angriff vom Server erkannt wird.

Das funktioniert natürlich nicht, wenn die angegriffene Webanwendung eine XSS-Schwachstelle enthält. Dann kann der Angreifer darüber Code einschleusen, der das Token ausspäht und den CSRF-Request danach mit dem korrekten Token-Wert quasi „on the fly“ erzeugt. Ein schönes Beispiel für so einen Fall ist der MySpace-Wurm „Samy“ [5]. MySpace schützte seine Formulare zwar mit einem zufälligen Hashwert vor CSRF-Angriffen, der im Kontext der MySpace-Website laufende Wurmcode konnte ihn aber einfach lesen und seine Requests damit korrekt formulieren. Rein formal handelt es sich dabei aber nicht mehr um Cross-Site Request Forgery, da die gefälschten Requests aus dem Kontext der angegriffenen Webanwendung heraus geschickt werden.

Kommen wir nun zu den aktuellen Entwicklungen rund um CSRF, und zwar anhand von Vorträgen auf den Black-Hat-Sicherheitskonferenzen. Los geht es mit einem Vortrag, der eine Variante des eben beschriebenen Problems der XSS-Schwachstellen behandelt.

Mit JavaScript-Schutzmaßnahmen gegen JavaScript-Schutzmaßnahmen

Der Vortrag stammt von Ahamed Nafeez und wurde auf der Black Hat Asia 2014 gehalten, und schon der Titel ist vielversprechend: „JS Suicide: Using JavaScript Security Features to Kill JS Security“ [6]. Der ganze Vortrag ist sehr interessant – uns interessiert aber nur ein Teilaspekt, nämlich der Schutz vor CSRF-Angriffen und wie man ihn unterlaufen kann. Konkret: Den vom OWASP CSRFGuard [7] implementierten Schutz für Java-Anwendungen.

OWASP CSRFGuard fügt die Anti-CSRF-Token über JavaScript dynamisch in die Webseiten ein, was voraussetzt, dass die Token der CSRFGuard Library bekannt sind. Dazu werden sie in die vom Browser geladene JavaScript-Bibliothek eingefügt – sicherheitshalber aber nur, wenn die Bibliothek auch wirklich von HTML geladen wird, das von der gleichen Website stammt. Sonst könnte ein Angreifer die Bibliothek herunterladen, um die Token auszuspähen. Dazu wird der Wert von document.domain geprüft:

if(isValidDomain(document.domain, "www.richtige-domain.example")) { … }

Dabei vergleicht isValidDomain einfach nur die übergebenen Strings. Aber was passiert, wenn document.domain einen falschen Wert liefert? Das ist möglich, da ein Angreifer darin seinen eigenen, gewünschten Wert speichern kann:

Object.defineProperty(document, 'domain', { get:function(){return 'www.richtige-domain.example'} });

Danach kann der Angreifer auf das vom Server gelieferte Token zugreifen und den CSRF-Schutz umgehen.

Man könnte versuchen, mithilfe von Object.isFrozen eine solche Manipulation zu erkennen, was leider daran scheitert, dass auch Object.isFrozen vom Angreifer m...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang