aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Webentwicklung

Was ist CSRF und wie funktioniert der Schutz von Webformularen

Während ein Nutzer auf deiner Seite angemeldet ist, kann eine andere bösartige Seite in seinem Namen Anfragen an deinen Server senden; das ist der Kern der Frage was ist CSRF. Cross-Site Request Forgery (seitenübergreifende Anfragefälschung) ist ein Angriff, der die Gewohnheit des Browsers ausnutzt, Cookies automatisch an jede Anfrage anzuhängen. Solange die Sitzung des Nutzers aktiv ist, kann ein Angreifer dessen Berechtigung „ausleihen", um zustandsändernde Aktionen auszulösen, etwa ein Passwort ändern, Geld überweisen oder Einstellungen aktualisieren. In diesem Artikel erkläre ich, wie der Angriff funktioniert, die Logik hinter Tokens und wie moderne Frameworks diese Verteidigung automatisieren, alles mit konkreten Beispielen.

Wie der Angriff Schritt für Schritt abläuft

Angenommen, eine Banking-App führt eine Überweisung mit einem Formular wie diesem aus:

<form action="https://bank.com/ueberweisung" method="POST">
  <input name="empfaenger" value="...">
  <input name="betrag" value="...">
</form>

Wenn der Nutzer eine völlig andere Seite besucht, während er noch bei der Bank angemeldet ist, kann diese Seite ein verstecktes Formular enthalten:

<form action="https://bank.com/ueberweisung" method="POST" id="boese">
  <input type="hidden" name="empfaenger" value="angreifer">
  <input type="hidden" name="betrag" value="10000">
</form>
<script>document.getElementById('boese').submit();</script>

Wenn der Browser die Anfrage sendet, fügt er automatisch das für die Bank registrierte Sitzungscookie hinzu. Aus Sicht des Servers sieht die Anfrage genau wie die eines legitimen Nutzers aus. Die Wurzel des Problems ist diese: Der Server kann nicht erkennen, ob die Anfrage wirklich von seiner eigenen Seite oder von einer fremden Herkunft stammt.

Die Token-Logik: das Synchronisations-Token

Die klassische Verteidigung ist das „Synchronizer Token Pattern". Der Server erzeugt für jede Sitzung einen unvorhersehbaren Zufallswert, speichert ihn in der Sitzung des Nutzers und bettet ihn als verstecktes Feld in das Formular der Seite ein:

<form method="POST" action="/ueberweisung">
  <input type="hidden" name="_token" value="a1b2c3...zufall">
  ...
</form>

Wenn das Formular abgeschickt wird, vergleicht der Server das eingehende _token mit dem in der Sitzung gespeicherten Wert. Stimmen sie nicht überein, wird die Anfrage abgelehnt. Die fremde Seite des Angreifers kann dieses Token nicht kennen, weil eine Seite von einer anderen Herkunft den Inhalt der Bankseite aufgrund der Same-Origin Policy nicht lesen kann. Das Token bleibt geheim und die gefälschte Anfrage wird ungültig.

Damit ein Token sicher ist, sollte es diese Eigenschaften haben:

  • Unvorhersehbar: erzeugt mit einem kryptografisch starken Zufallsgenerator.
  • An die Sitzung oder den Nutzer gebunden: das Token eines Nutzers darf für einen anderen nicht gültig sein.
  • Nur für zustandsändernde Anfragen erforderlich: schreibgeschützte Anfragen wie GET sollten ohnehin keine Nebenwirkungen haben.

Die Double-Submit-Cookie-Methode

Für zustandslose (stateless) APIs, die keinen Sitzungszustand auf dem Server halten wollen, gibt es ein alternatives Muster: das Double Submit Cookie. Hier wird das Token sowohl in ein Cookie als auch in einen Anfrage-Header (oder den Body) geschrieben. Der Server prüft, ob beide gleich sind. Eine fremde Seite kann das Cookie einer anderen Herkunft nicht per JavaScript auslesen, um es in den Header zu kopieren, daher schlägt der Angriff fehl. Sein einziger Nachteil ist, dass er eine sorgfältige Konfiguration bei Themen wie dem Vertrauen zwischen Subdomains erfordert.

SameSite-Cookies: Verteidigung auf Browserebene

Das den Cookies hinzugefügte Attribut SameSite teilt dem Browser mit, ob das Cookie bei seitenübergreifenden Anfragen gesendet werden soll. Es gibt drei Werte:

  • SameSite=Strict: Das Cookie wird nur an Anfragen von derselben Seite angehängt; es wird nicht einmal beim Folgen eines externen Links gesendet.
  • SameSite=Lax: Es wird an GET-Anfragen bei der Navigation auf oberster Ebene angehängt, aber nicht an seitenübergreifende POSTs. Dies ist die Voreinstellung in den meisten modernen Browsern.
  • SameSite=None; Secure: Es wird in allen Fällen gesendet; verwende es, wenn du wirklich ein seitenübergreifendes Cookie brauchst.

Lax oder Strict bietet eine starke Schicht gegen CSRF, weil das Sitzungscookie niemals an einen vom Angreifer ausgelösten seitenübergreifenden POST angehängt wird. Dennoch gilt SameSite allein nicht als ausreichend; für ältere Browser und bestimmte Grenzfälle ist es der robusteste Ansatz, den Token-Schutz parallel zu verwenden. Eine geschichtete Verteidigung ist entscheidend.

Wie Frameworks dies automatisieren

Moderne Frameworks übernehmen die Token-Erzeugung und -Validierung für dich. In Laravel fügt zum Beispiel die Blade-Direktive @csrf das versteckte Token-Feld zum Formular hinzu, und die VerifyCsrfToken-Middleware validiert es automatisch bei jeder POST-, PUT-, PATCH- und DELETE-Anfrage:

<form method="POST" action="/profil">
  @csrf
  <input name="name">
  <button>Speichern</button>
</form>

Wenn du eine Anfrage mit JavaScript stellst (zum Beispiel fetch), musst du das Token aus einem <meta>-Tag lesen und dem Header hinzufügen:

const token = document.querySelector('meta[name="csrf-token"]').content;
fetch('/profil', {
  method: 'POST',
  headers: {
    'X-CSRF-TOKEN': token,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ name: 'Aslain' })
});

Die Logik ist in anderen Ökosystemen dieselbe: Django verwendet {% csrf_token %} und CsrfViewMiddleware, Rails verwendet protect_from_forgery und Express setzt für dieselbe Aufgabe auf Pakete vom Typ csurf. APIs, die keine cookiebasierten Sitzungen verwenden (zum Beispiel solche, die bei jeder Anfrage einen Authorization: Bearer-Header mitführen), sind von Natur aus widerstandsfähiger gegen CSRF, weil der Browser diesen Header nicht automatisch anhängt.

Praktische Checkliste

  • Schütze jeden zustandsändernden Endpunkt (POST/PUT/PATCH/DELETE) mit CSRF-Validierung.
  • Füge SameSite=Lax (oder Strict, wo angebracht) und Secure zu Sitzungscookies hinzu.
  • Lass das Token niemals in einer URL oder einem Log durchsickern; verwende ein verstecktes Formularfeld oder einen Anfrage-Header.
  • Halte GET-Anfragen frei von Nebenwirkungen; verwende sie nicht zum Ändern von Daten.
  • Deaktiviere den eingebauten Schutz des Frameworks nicht; wenn es wirklich sein muss, nimm nur die betreffende Route aus.

Häufige Fragen

Sind CSRF und XSS dasselbe?

Nein. XSS bedeutet, dass ein Angreifer ein bösartiges Skript in deine Seite einschleust und sogar den Token-Schutz umgehen kann. CSRF bedeutet, die bestehende Sitzung des Nutzers von außen zu missbrauchen. Wenn eine XSS-Schwachstelle existiert, kann auch deine CSRF-Verteidigung zusammenbrechen, weshalb beide zusammen behandelt werden müssen.

Verhindert allein die Nutzung von HTTPS CSRF?

Nein. HTTPS verschlüsselt Daten und erschwert Man-in-the-Middle-Angriffe, kümmert sich aber nicht darum, woher die Anfrage stammt. Für CSRF brauchst du weiterhin Tokens und/oder SameSite-Cookies.

Muss sich das Token bei jeder Anfrage ändern?

Nicht unbedingt. Ein Token, das für die Sitzung fest, aber an sie gebunden ist, reicht in den meisten Fällen aus. Ein bei jeder Anfrage neu erzeugtes Token bietet zusätzliche Sicherheit, kann aber Probleme mit der Zurück-Taste und der Nutzung mehrerer Tabs verursachen; deshalb verwenden die meisten Frameworks ein einziges Token für die gesamte Lebensdauer der Sitzung.

Möchtest du deine Formulare absichern oder eine bestehende Anwendung prüfen? Ich entwickle praktische Lösungen für CSRF, XSS und Sitzungssicherheit. Kontaktiere mich und lass uns dein Projekt gemeinsam härten.

Bu kategorideki tüm yazılar →

Devamı için