Zum Inhalt springen

Cross-Site Request Forgery (CSRF)

CWE-352OWASP A01:2021Aktualisiert 29. August 20265 Min. Lesezeit

Cross-Site Request Forgery (CSRF) ist eine Schwachstelle, bei der der Browser eines angemeldeten Nutzers unbemerkt eine Anfrage absendet. Die Website führt diese Anfrage aus, als käme sie vom Nutzer selbst, sodass Aktionen wie eine Passwortänderung oder eine Überweisung ohne Einwilligung des Opfers ausgeführt werden.

Cross-Site Request Forgery, kurz CSRF, geht es nicht ums Stehlen von Daten, sondern um den Missbrauch von Vertrauen: Ihr eigener Nutzer führt, ohne es zu ahnen, eine Aktion aus, die der Angreifer für ihn vorbereitet hat. In diesem Artikel erfahren Sie, was CSRF ist, wie ein solcher Angriff abläuft, was ein Angreifer damit erreichen kann und wie Sie Ihre Anwendung dagegen absichern.

Was ist Cross-Site Request Forgery?

Cross-Site Request Forgery (CSRF) ist eine Schwachstelle, bei der ein Angreifer den Browser eines angemeldeten Nutzers missbraucht, um eine ungewollte, zustandsändernde Aktion auf einer Website auszuführen, bei der dieser Nutzer angemeldet ist. Das Opfer bemerkt nichts davon: Ein einziger Besuch einer präparierten Seite genügt, um im Hintergrund eine Anfrage abzufeuern, die die Zielseite als völlig legitim behandelt.

Der Kern des Problems ist eine Gewohnheit des Browsers. Stellen Sie sich eine Bank vor, die jeden Auftrag ausführt, solange er in einem Umschlag mit Ihrem persönlichen Siegel steckt. Ein Betrüger kann dieses Siegel nicht fälschen, aber er kann Ihnen ein fertiges Auftragsschreiben zuschieben und Sie dazu verleiten, es in Ihren eigenen, bereits versiegelten Umschlag zu legen. Der Umschlag ist hier Ihr Session-Cookie: Der Browser heftet es automatisch an jede Anfrage an die Bank, auch an eine, die von einer fremden Seite angestoßen wurde. Die Website sieht ein gültiges Siegel und gehorcht.

Wie funktioniert ein CSRF-Angriff?

CSRF lauert überall dort, wo eine Anwendung eine sensible Aktion allein auf Basis des Session-Cookies ausführt: eine E-Mail-Adresse ändern, ein Passwort zurücksetzen, Geld überweisen oder Rechte vergeben. Weil der Browser dieses Cookie unaufgefordert mitschickt, muss der Angreifer die Zugangsdaten gar nicht kennen.

Verwundbar:

// Ändert die E-Mail-Adresse, vertraut allein auf das Session-Cookie
app.post('/account/email', (req, res) => {
  if (!req.session.userId) return res.status(401).send('Nicht angemeldet');
  updateEmail(req.session.userId, req.body.email);
  res.send('E-Mail-Adresse aktualisiert');
});

Dieser Endpunkt prüft nur, ob eine gültige Sitzung besteht, und übernimmt die Änderung anschließend bedenkenlos. Nirgends wird geprüft, ob die Anfrage tatsächlich von der eigenen Website stammt. Der Angreifer muss also lediglich eine Seite bauen, die diese Anfrage im Namen des Opfers absendet, und einen angemeldeten Nutzer dazu bringen, sie zu öffnen.

<!-- Liegt auf der Seite des Angreifers und sendet sich sofort selbst ab -->
<form action="https://bank.example/account/email" method="POST">
  <input type="hidden" name="email" value="angreifer@boese.example">
</form>
<script>document.forms[0].submit()</script>

Sobald das Opfer diese Seite öffnet (über eine Phishing-Mail, eine Werbeanzeige oder einen versteckten Frame), sendet der Browser das Formular ab, inklusive des Session-Cookies für die Bank. Die E-Mail-Adresse des Kontos wird auf die des Angreifers geändert, der anschließend eine Passwortzurücksetzung anfordert und das Konto übernimmt. Ein gestohlenes Passwort kommt dabei nicht ins Spiel.

Sicher:

import { randomBytes, timingSafeEqual } from 'node:crypto';

// Beim Anzeigen des Formulars: Token erzeugen und in der Sitzung speichern
app.get('/account/email', (req, res) => {
  req.session.csrfToken = randomBytes(32).toString('hex');
  res.render('email-form', { csrfToken: req.session.csrfToken });
});

app.post('/account/email', (req, res) => {
  if (!req.session.userId) return res.status(401).send('Nicht angemeldet');

  const expected = req.session.csrfToken ?? '';
  const received = req.body.csrfToken ?? '';
  const ok = expected.length === received.length
    && timingSafeEqual(Buffer.from(expected), Buffer.from(received));
  if (!ok) return res.status(403).send('Ungültiges CSRF-Token');

  updateEmail(req.session.userId, req.body.email);
  res.send('E-Mail-Adresse aktualisiert');
});

Die sichere Variante fügt ein Geheimnis hinzu, das der Angreifer unmöglich erraten kann. Beim Abruf des Formulars erhält der Nutzer ein zufälliges Token, das der Server ebenfalls in der Sitzung ablegt. Beim Absenden muss genau dieses Token wieder mitkommen, und der Server vergleicht beide mit einer zeitkonstanten Prüfung. Die Seite des Angreifers kennt dieses Token nicht (die Antwort mit dem Formular kann sie schließlich nicht auslesen) und ihre Anfrage läuft in einen 403. Setzen Sie zusätzlich das Session-Cookie auf SameSite=Lax oder Strict, damit der Browser das Cookie bei einer Anfrage von einer fremden Seite ohnehin nicht mehr mitschickt.

Ein CSRF-Token schützt nicht vor einem Angreifer, der bereits Skripte auf Ihrer Seite ausführen kann. Über Cross-Site Scripting (XSS) liest er das Token einfach aus und umgeht die gesamte Verteidigung. Behandeln Sie XSS und CSRF daher als zwei Schwachstellen, die Sie beide schließen müssen.

Welche Auswirkungen hat CSRF?

Der Schweregrad von CSRF ist in der Regel mittel, und das hat einen klaren Grund. Wegen der Same-Origin-Policy kann der Angreifer die Antwort nicht auslesen; er sendet seine Anfrage blind und braucht zudem ein angemeldetes Opfer, das er auf seine Seite locken kann. CSRF stiehlt also keine Daten, sondern erzwingt Aktionen.

Dennoch kann diese eine erzwungene Aktion schwer wiegen. Wird die E-Mail-Adresse oder das Passwort geändert, folgt oft eine vollständige Kontoübernahme. Weitere klassische Ziele sind eine Überweisung, das Anpassen von Rechten, das Hinzufügen eines Administrators oder das Ändern von Einstellungen, die die Sicherheit schwächen. In einer Administrationsoberfläche kann eine einzige erfolgreiche CSRF-Anfrage die Konfiguration eines ganzen Systems umstellen. Der Schaden für das Unternehmen reicht damit von einem gekaperten Kundenkonto bis hin zu Reputations- und finanziellem Verlust, genau deshalb sollten Sie auch eine “mittelschwere” Schwachstelle wie diese nicht offen lassen.

Wie spürt man CSRF auf?

Bei einem Test geht ein Pentester jede zustandsändernde Aktion durch (alles, was etwas anlegt, ändert oder löscht) und prüft, ob die Anfrage durch ein unvorhersehbares, pro Sitzung eindeutiges Token geschützt ist. Anschließend wird dieses Token weggelassen, aus einer anderen Sitzung wiederverwendet oder leicht verändert, um zu sehen, ob der Server die Anfrage trotzdem ausführt. Auch die SameSite-Einstellung des Session-Cookies und die Prüfung der Origin- und Referer-Header werden kontrolliert. Endpunkte, die den Zustand über eine GET-Anfrage ändern, sind ein klassisches Warnsignal, denn sie lassen sich trivial missbrauchen. Automatisierte Scanner melden ein fehlendes Token, beurteilen aber selten, ob die Token-Prüfung tatsächlich lückenlos ist. AssistSec berücksichtigt CSRF standardmäßig in einem Penetrationstest und prüft gezielt jene Randfälle, in denen ein Token zwar vorhanden scheint, aber nicht korrekt validiert wird.

Wie verhindert man CSRF?

  • Schützen Sie jede zustandsändernde Aktion mit dem Synchronizer-Token-Muster: einem unvorhersehbaren Token pro Sitzung, das der Server bei jeder Anfrage überprüft.
  • Setzen Sie Session-Cookies auf SameSite=Lax oder SameSite=Strict, ergänzt um Secure und HttpOnly.
  • Führen Sie eine Änderung niemals über eine GET-Anfrage aus; reservieren Sie GET für das Abrufen von Daten.
  • Prüfen Sie bei sensiblen Aktionen die Origin- und Referer-Header als zusätzliche Schicht.
  • Verlangen Sie für kritische Vorgänge (Passwort- oder E-Mail-Änderung, Zahlungen) erneut das Passwort oder einen zweiten Faktor.
  • Verlassen Sie sich auf den eingebauten CSRF-Schutz Ihres Frameworks, statt selbst einen zu bauen, und lassen Sie ihn aktiviert.
  • Schließen Sie Cross-Site Scripting konsequent, denn XSS umgeht jedes CSRF-Token, das Sie einrichten.

Quellen

Häufige Fragen

Was ist der Unterschied zwischen CSRF und XSS?

Bei XSS schleust ein Angreifer Schadskripte ein, die im Browser des Opfers laufen und Daten auslesen können. Bei CSRF läuft kein Skript auf der Zielseite; der Angreifer bringt den Browser lediglich dazu, eine Anfrage zu senden, und missbraucht das dabei mitgeschickte Session-Cookie. XSS ist zudem ein gängiger Weg, um CSRF-Schutz auszuhebeln.

Schützt HTTPS vor CSRF?

Nein. HTTPS verschlüsselt den Datenverkehr, aber eine CSRF-Anfrage ist selbst eine gültige, korrekt aufgebaute Anfrage. Die Verschlüsselung ändert nichts daran, dass der Browser das Session-Cookie automatisch mitschickt. Sie brauchen ein CSRF-Token oder ein striktes SameSite-Cookie.

Reicht ein SameSite-Cookie allein gegen CSRF?

SameSite=Lax oder Strict blockiert die meisten klassischen Angriffe und ist eine starke Grundschicht, deckt aber nicht jedes Szenario ab, etwa Subdomains, ältere Browser oder GET-Anfragen, die den Zustand ändern. Kombinieren Sie SameSite daher mit einem CSRF-Token für sensible Aktionen.

Kann ein CSRF-Angriff die Antwort auslesen?

Nein. Die Same-Origin-Policy hindert den Angreifer daran, die Antwort des Opfers zu lesen. Die Anfrage wird blind gesendet. Deshalb ist CSRF vor allem für Aktionen gefährlich, die etwas verändern, nicht für den Diebstahl von Daten.

Verwandte Artikel

Zum Suchen / drücken · Esc