Vor XSS und CSRF schützen
Zwei der häufigsten Web-Sicherheitslücken erklärt, welche konkreten Schutzmaßnahmen tatsächlich wirken, welche Sonderfälle in der Praxis regelmäßig übersehen werden, und wie sich beide Lücken gezielt prüfen lassen.
XSS und CSRF gehören seit Jahren zu den am häufigsten ausgenutzten Sicherheitslücken im Web. Beide zielen auf den Browser eines eingeloggten Nutzers, funktionieren aber grundlegend unterschiedlich - und erfordern entsprechend unterschiedliche Schutzmaßnahmen. Dieser Artikel geht über die Grundregel “escapen und Tokens verwenden” hinaus und arbeitet die Mechanismen, Sonderfälle und Prüfschritte auf, die in der Praxis tatsächlich entscheiden, ob eine Anwendung geschützt ist.
1. Wie sich die Angriffe im Kern unterscheiden
XSS (Cross-Site Scripting) schleust schädlichen Code direkt in eine Website ein, der dann im Browser anderer Nutzer mit deren Rechten ausgeführt wird - der Angreifer bringt fremden Code zur Ausführung im Kontext der angegriffenen Seite. CSRF (Cross-Site Request Forgery) hingegen führt keinen fremden Code aus, sondern missbraucht die automatische Cookie-Übertragung des Browsers, um eine bestehende, eingeloggte Session für unerwünschte Aktionen zu nutzen - der Angreifer bringt den Browser lediglich dazu, eine legitime Anfrage im Namen des Opfers abzuschicken. Dieser Unterschied ist der Grund, warum die beiden Schutzmaßnahmen sich nicht gegenseitig ersetzen.
2. Die drei Arten von XSS
Reflektiertes XSS entsteht, wenn Nutzereingaben (etwa aus einem URL-Parameter) ungeprüft direkt in der Antwortseite ausgegeben werden - der schädliche Code steckt im Link selbst und wirkt nur, wenn das Opfer diesen präparierten Link anklickt. Persistentes (gespeichertes) XSS entsteht, wenn schädlicher Code dauerhaft gespeichert wird, etwa in einem Kommentarfeld oder Profilnamen, und danach jedem Besucher der betroffenen Seite ausgeliefert wird, ohne dass ein präparierter Link nötig ist - dadurch gilt persistentes XSS grundsätzlich als die schwerwiegendere Variante. DOM-basiertes XSS entsteht rein clientseitig, wenn JavaScript im Browser selbst nicht vertrauenswürdige Daten (etwa Teile der URL) ungeprüft in den DOM einfügt, ohne dass der Server an der eigentlichen Schwachstelle beteiligt ist.
3. Schutz vor XSS: Escaping als Grundlage
Der wirksamste Schutz gegen XSS ist konsequentes Escaping aller Nutzereingaben beim Anzeigen im Browser - Sonderzeichen wie < und > dürfen nicht ungeprüft als HTML interpretiert werden. Entscheidend dabei ist, kontextabhängig zu escapen: Eine Ausgabe innerhalb von HTML-Text braucht andere Escaping-Regeln als eine Ausgabe innerhalb eines HTML-Attributs, innerhalb eines <script>-Blocks oder innerhalb einer URL. Moderne Frontend-Frameworks übernehmen dieses kontextabhängige Escaping standardmäßig für alle regulär gebundenen Werte, sofern Entwickler nicht bewusst rohes HTML einbinden (etwa über Funktionen, deren Name meist ausdrücklich auf “raw”, “unsafe” oder “html” hinweist) - genau diese bewussten Ausnahmen sind in der Praxis die häufigste Quelle echter XSS-Lücken in ansonsten modernen Anwendungen.
4. Schutz vor XSS: Content Security Policy als zweite Verteidigungslinie
Eine zusätzliche Verteidigungsebene bietet eine Content Security Policy (CSP), die im Browser einschränkt, welche Skriptquellen überhaupt ausgeführt werden dürfen. Eine restriktive CSP kann selbst dann verhindern, dass eingeschleuster Code tatsächlich zur Wirkung kommt, wenn eine Escaping-Lücke übersehen wurde - sie wirkt damit als Netz für den Fall, dass die erste Verteidigungslinie versagt, ersetzt konsequentes Escaping aber nicht. Eine CSP, die Inline-Skripte pauschal erlaubt oder beliebige externe Skriptquellen zulässt, bietet gegen XSS entsprechend wenig Schutz.
5. Schutz vor CSRF: Tokens
Gegen CSRF hat sich der Einsatz von CSRF-Tokens etabliert: ein zufälliger, pro Sitzung oder pro Formular generierter Wert, der bei jeder sicherheitsrelevanten Anfrage mitgeschickt und serverseitig geprüft wird. Ohne gültigen, zur Session passenden Token wird die Anfrage abgelehnt, selbst wenn gültige Session-Cookies automatisch mitgesendet wurden. Der Token funktioniert, weil eine fremde, angreifende Website ihn nicht kennt - sie kann zwar den Browser dazu bringen, eine Anfrage mit den echten Cookies abzuschicken, aber nicht dazu, den korrekten, serverseitig erwarteten Token mitzusenden.
6. Schutz vor CSRF: SameSite-Cookies
Ergänzend hilft das SameSite-Attribut bei Cookies, das die automatische Übertragung von Cookies bei Anfragen einschränkt, die von einer fremden Website ausgelöst werden. Je nach eingestelltem Wert werden Cookies bei solchen fremdausgelösten Anfragen entweder komplett zurückgehalten oder nur bei bestimmten, als risikoarm geltenden Anfragearten (etwa einfache Navigation über einen Link) noch mitgesendet. SameSite-Cookies sind eine wirksame, browserseitige Ergänzung, aber kein vollständiger Ersatz für CSRF-Tokens: Sie hängen von korrekter Browser-Unterstützung ab und schützen nicht in jeder denkbaren Angriffskonstellation, etwa wenn eine Subdomain derselben Seite kompromittiert ist.
7. Warum GET-Anfragen für zustandsändernde Aktionen ein eigenes Risiko sind
Eine Anwendung, die zustandsändernde Aktionen (Passwort ändern, Bestellung auslösen, Konto löschen) über eine einfache GET-Anfrage abwickelt, ist für CSRF besonders anfällig: Ein Angreifer muss dann nicht einmal ein Formular automatisch absenden lassen, ein einfaches, unauffälliges Bild-Tag oder ein Link mit der passenden URL genügt bereits, um die Aktion im Browser des Opfers auszulösen. Zustandsändernde Aktionen gehören deshalb grundsätzlich auf POST- oder andere nicht-idempotente HTTP-Methoden, kombiniert mit CSRF-Token-Prüfung - GET-Anfragen sollten laut HTTP-Konvention ohnehin keine Seiteneffekte auslösen.
8. Wo CORS in diesem Bild steht - und wo nicht
CORS (Cross-Origin Resource Sharing) wird häufig fälschlich als CSRF-Schutz missverstanden. Tatsächlich regelt CORS, ob eine fremde Website die Antwort einer Cross-Origin-Anfrage per JavaScript auslesen darf - es verhindert aber nicht, dass die Anfrage selbst abgeschickt und serverseitig ausgeführt wird. Bei einem klassischen CSRF-Angriff ist der Angreifer an der Antwort gar nicht interessiert, sondern nur daran, dass die Aktion (z. B. eine Zahlung) ausgeführt wird - eine restriktive CORS-Konfiguration allein verhindert das nicht. CORS und CSRF-Schutz adressieren unterschiedliche Risiken und ergänzen sich, ersetzen sich aber nicht.
9. Warum beide Schutzmaßnahmen unabhängig voneinander nötig sind
Da XSS und CSRF unterschiedliche Schwachstellen ausnutzen, schützt keine der beiden Maßnahmen vor der jeweils anderen Angriffsart. Eine Anwendung mit sauberer CSRF-Token-Prüfung, aber ungeprüften Nutzereingaben bleibt für XSS anfällig - und umgekehrt. Problematisch wird es zudem, wenn beide Lücken kombiniert auftreten: Eine erfolgreiche XSS-Lücke kann genutzt werden, um den CSRF-Token direkt aus der Seite selbst auszulesen (da der eingeschleuste Code im selben Ursprungskontext läuft) und damit auch eine ansonsten korrekt implementierte CSRF-Prüfung zu umgehen. Konsequentes XSS-Escaping ist damit indirekt auch eine Voraussetzung für die Wirksamkeit von CSRF-Schutz.
10. Häufige Fehler
Ein verbreiteter Fehler ist, Nutzereingaben zwar beim Speichern zu validieren, aber nicht kontextabhängig beim Ausgeben zu escapen - Validierung und Escaping adressieren unterschiedliche Risiken und ersetzen sich nicht gegenseitig. Ein zweiter Fehler ist, CSRF-Schutz nur für das offensichtliche Login-Formular zu implementieren, während andere zustandsändernde Endpunkte (etwa API-Routen, die von JavaScript aus aufgerufen werden) ausgenommen bleiben. Ein dritter Fehler ist, sich bei serverseitig gerenderten Formularen ausschließlich auf SameSite-Cookies zu verlassen, ohne echte Token-Prüfung - das funktioniert nur so lange zuverlässig, wie kein Sonderfall (etwa eine kompromittierte Subdomain oder ein älterer Browser) eintritt.
11. Wie prüfst du das
Für XSS lässt sich in den Entwicklertools des Browsers prüfen, ob typische Testzeichen wie < in Eingabefeldern beim Anzeigen tatsächlich als Text und nicht als HTML interpretiert werden - erscheint ein eingegebenes <script>-Tag im gerenderten DOM als ausführbares Element statt als sichtbarer Text, liegt eine Escaping-Lücke vor. Für CSRF lässt sich prüfen, ob eine zustandsändernde Anfrage ganz ohne mitgesendeten Token oder mit einem offensichtlich falschen Token vom Server tatsächlich abgelehnt wird - akzeptiert der Server die Anfrage trotzdem, ist die Prüfung serverseitig nicht wirksam implementiert, unabhängig davon, ob ein Token-Feld im Formular vorhanden ist. Beide Prüfungen lassen sich manuell mit den Browser-Entwicklertools durchführen, ohne spezialisierte Sicherheitswerkzeuge.
12. Praktischer Ausgangspunkt
Wer eine bestehende Anwendung absichern will, sollte in dieser Reihenfolge vorgehen: erstens prüfen, ob Nutzereingaben an jeder Ausgabestelle kontextabhängig escaped werden und ob es bewusste “raw HTML”-Ausnahmen gibt, die eine erneute Prüfung rechtfertigen; zweitens prüfen, ob sämtliche zustandsändernden Formulare und API-Endpunkte tatsächlich CSRF-Tokens verwenden und diese serverseitig verifizieren, nicht nur die offensichtlichen; drittens eine CSP als zusätzliche Absicherung einführen; viertens SameSite-Cookies als ergänzende, aber nicht alleinige Maßnahme setzen. Alle vier Punkte lassen sich in den meisten modernen Web-Frameworks über eingebaute Mechanismen aktivieren, statt sie von Grund auf selbst zu implementieren.