Begriff
CSRF (Cross-Site Request Forgery)
Warum wichtig?
Dieser Begriff ist ein Knoten im SengakujiWorks-Wissensnetz. Nutze Level 0 für die erste Einordnung, Level 1 für Praxis, Level 2 für technische Struktur und Level 3 für Grenzen, Fallstricke und Expertenkontext.
Du bist bei deiner Bank eingeloggt (bank.com).
Du besuchst eine böse Webseite (hacker.com).
Auf der bösen Seite ist ein unsichtbares Bild:
<img src="http://bank.com/transfer?to=hacker&amount=1000">
Dein Browser will das Bild laden. Er sendet eine Anfrage an die Bank.
Da du dort eingeloggt bist, klebt der Browser dein Session-Cookie automatisch an die Anfrage.
Die Bank denkt: "Ah, der User will Geld überweisen. Cookie passt. Mache ich."
Geld weg.
Der Hacker hat deinen Browser "ferngetsuert", ohne dass er dein Passwort kannte.
Merksatz: Ein Angriff, bei dem ein Angreifer den Browser des Opfers dazu bringt, eine ungewollte HTTP-Anfrage an eine vertrauenswürdige Webseite zu senden, auf der das Opfer authentifiziert ist.
Der Schutz: Anti-CSRF Token.
Jedes Formular der Bank enthält ein geheimes Zufallsfeld:
<input type="hidden" name="csrf_token" value="abc123random">
Die böse Seite (hacker.com) kennt dieses Token nicht.
Wenn der Browser den Request von hacker.com sendet, fehlt das Token.
Die Bank lehnt ab: "Cookie ist da, aber Token fehlt. Angriff!"
1. SameSite Cookies
Der moderne Schutz (Browser-Ebene).
Du setzt beim Cookie das Flag SameSite=Strict oder Lax.
- Strict: Der Browser sendet das Cookie nie, wenn der Link von einer fremden Seite kommt. (Sicher, aber nervig: Wenn du aus einer Email auf Facebook klickst, bist du ausgeloggt).
- Lax: Erlaubt GET-Requests (normale Links), aber blockiert POST (Formulare/Bilder) von fremden Seiten. (Guter Kompromiss).
2. JSON APIs & CSRF
CSRF funktioniert fast nur mit Formularen (POST) oder Links (GET).
Wenn deine API nur JSON akzeptiert (Content-Type: application/json), ist sie oft sicher vor simplem CSRF.
Warum? Ein <form> kann kein JSON senden. Ein <img> auch nicht.
Der Hacker müsste JavaScript (XHR/Fetch) nutzen. Das verbietet aber die Same-Origin-Policy (SOP), solange CORS nicht falsch konfiguriert ist.
3. Login CSRF
Der Hacker loggt dich in seinen Account ein. Du googlest etwas. Aber du bist dabei unwissentlich in den Google-Account des Hackers eingeloggt. Er sieht später in seiner History, was du gesucht hast. Selten, aber kreativ.
SameSite Cookies: Tücken der Implementierung
Das SameSite-Attribut (insbesondere Lax und Strict) gilt als der moderne Sargnagel für klassisches CSRF, da Browser es inzischen by default erzwingen. Aber Vorsicht:
SameSite prüft die eTLD+1 (Effective Top-Level Domain).
Wenn die Bank app.bank.com nutzt und der Angreifer kontrolliert forum.bank.com, greift SameSite nicht, da beide zur selben Site (bank.com) gehören!
Zudem umgehen fehlerhafte Client-Side-Frameworks den Schutz oft. Wenn die App auf GET-Requests statusändernde Aktionen erlaubt (z.B. <img src="bank.com/api/delete_account">), greift SameSite=Lax ebenfalls nicht, da GET-Requests für Cross-Site Navigation standardmäßig weiterhin das Cookie mitsenden.
Der Synchronizer Token Pattern (Stateless vs. Stateful)
Der klassische Ansatz: Das Backend generiert ein kryptografisch starkes Zufalls-Token, speichert es in der User-Session (RAM/Redis) und injectet es ins HTML (<input type="hidden">).
Wenn Formulare gesendet werden, vergleicht das Backend Session.Token === PostData.Token. Das ist extrem sicher, verhindert aber Skalierbarkeit (Stateful Backend).
Modernes REST-Design bricht mit diesem Server-State. Stattdessen wird oft das Double Submit Cookie Pattern verwandt, bei dem der Server das Token in einem (lesbaren) Cookie an den Client gibt. Der Client-Code (JS) liest das Cookie aus und legt es als HTTP-Header (X-CSRF-TOKEN) bei jedem Request bei. Ein Angreifer kann das Cookie des Opfers zwar per CSRF senden lassen, das Cookie per Script aber nicht auslesen, was das Kopieren in den Payload-Header für ihn unmöglich macht.
CORS Misconfigurations leading to CSRF
Viele Entwickler denken, CORS (Cross-Origin Resource Sharing) schützt vor CSRF. Das ist ein Mythos.
CORS blockiert niemals, dass ein Request an den Server gesendet wird. CORS verhindert lediglich, dass der Angreifer die Antwort (Response) per JavaScript lesen darf.
Eine statusändernde Aktion (Überweisung tätigen) wird vom Browser ausgeführt, bevor die SOP/CORS zuschlägt.
Katastrophal wird es, wenn die Bank-API Access-Control-Allow-Origin: * gepaart mit Access-Control-Allow-Credentials: true setzt. (Dies verbietet die Spec zwar offiziell, aber viele APIs umschiffen dies, indem sie dynamisch den Origin des Angreifers als freigegeben eintragen if (req.header.origin) response.set('Allow-Origin', req.header.origin)). In diesem Fall kann der Angreifer per Fetch-API echte authentifizierte Requests abfeuern und die geheimen Resultate lesen.
Quick-Check
Bedingung für CSRF?
Das Opfer muss auf der Zielseite eingeloggt sein. Wenn du ausgeloggt bist, passiert nix (Session-Cookie fehlt). Darum: "Immer ausloggen bei Online-Banking!"Unterschied zu XSS?
Bei CSRF nutzt der Hacker deinen eigenen Browser gegen den Server, aber er sieht die Antwort nicht. (Er kann überweisen, aber nicht deinen Kontostand lesen). Bei XSS kontrolliert er alles.Double Submit Cookie?
Eine CSRF-Abwehr für Stateless Apps. Man sendet das Token im Cookie UND im Header. Der Hacker kann das Cookie nicht lesen und deshalb nicht in den Header kopieren. Der Server prüft, ob beide gleich sind.