XSS-Schutz: Der vollständige Leitfaden gegen Cross-Site-Scripting
Cross-Site-Scripting (XSS) ist seit über 20 Jahren unter den Top-Schwachstellen im Web — und bleibt es. Bei XSS schleust ein Angreifer schädlichen JavaScript-Code in Ihre Website ein, der im Browser anderer Benutzer ausgeführt wird. Die Folgen: Cookie-Diebstahl, Session-Hijacking, Phishing und Datenverlust.
Die drei XSS-Typen
1. Reflected XSS (Nicht-persistent)
Der Schadcode wird über einen URL-Parameter eingeschleust und vom Server in der Antwort reflektiert.
Angriffsszenario: Ein Angreifer erstellt eine URL mit eingebettetem Script-Tag im Suchparameter. Der Server gibt den Suchbegriff unescaped zurück und der Browser führt den Code aus.
Verbreitung: Phishing-E-Mails mit manipulierten Links.
2. Stored XSS (Persistent)
Der Schadcode wird in der Datenbank gespeichert und bei jedem Seitenaufruf an alle Besucher ausgeliefert.
Angriffsszenario: Ein Angreifer hinterlässt einen Kommentar mit eingebettetem JavaScript. Jeder Besucher, der die Kommentarseite öffnet, führt das Script aus.
Risiko: Deutlich höher als Reflected XSS, da keine Benutzerinteraktion (Klick auf Link) nötig ist.
3. DOM-Based XSS
Der Schadcode wird clientseitig ausgeführt, ohne dass der Server beteiligt ist. Unsichere DOM-Manipulation (z.B. Einfügen von URL-Parametern direkt in den DOM) ermöglicht die Ausführung von Schadcode.
Besonders tückisch: Serverseitige Scanner erkennen DOM-XSS oft nicht.
Auswirkungen eines XSS-Angriffs
| Angriff | Folge | |---|---| | Cookie-Diebstahl | Angreifer übernimmt die Session des Opfers | | Keylogging | Tastatureingaben werden mitgeschnitten (Passwörter, Kreditkarten) | | Phishing | Gefälschtes Login-Formular in der echten Website | | Defacement | Sichtbare Verunstaltung der Website | | Malware-Verteilung | Drive-by-Downloads über die kompromittierte Seite | | Kryptomining | Browser des Besuchers für Mining missbraucht |
Schutzmaßnahmen: 6 Verteidigungslinien
Linie 1: Output Encoding (wichtigste Maßnahme)
Regel: Alle Benutzerdaten werden beim Rendern im HTML escaped.
| Kontext | Encoding | Beispiel |
|---|---|---|
| HTML Body | HTML Entity Encoding | < wird < |
| HTML Attribute | Attribut-Encoding | " wird " |
| JavaScript | JavaScript Encoding | ' wird \x27 |
| URL Parameter | URL Encoding | < wird %3C |
| CSS | CSS Encoding | \3C |
Frameworks mit Auto-Escaping:
| Framework | Auto-Escape | Achtung |
|---|---|---|
| React | Ja (JSX escaped per Default) | Unsichere Raw-HTML-Methoden umgehen den Schutz |
| Angular | Ja (Template-Binding escaped) | Trust-Bypass-Methoden umgehen den Schutz |
| Vue.js | Ja (Template-Syntax escaped) | v-html Direktive umgeht den Schutz |
| Django | Ja (Templates escaped) | safe Filter umgeht den Schutz |
Regel: Verwenden Sie nie die Escape-Bypass-Funktionen mit Benutzerdaten.
Linie 2: Input-Validierung
Validieren Sie alle Eingaben serverseitig:
import { z } from 'zod'
const commentSchema = z.object({
name: z.string().min(1).max(100).regex(/^[a-zA-ZäöüÄÖÜß\s-]+$/),
comment: z.string().min(1).max(5000),
email: z.string().email(),
})
Wichtig: Input-Validierung ist eine zusätzliche Schutzschicht, kein Ersatz für Output Encoding.
Linie 3: Content Security Policy (CSP)
CSP ist Ihre stärkste Verteidigungslinie auf Header-Ebene:
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'
Selbst wenn ein XSS-Angriff die ersten beiden Linien durchbricht, verhindert CSP die Ausführung von Inline-Scripts und das Laden externer Scripts.
Linie 4: HTML-Sanitization
Wenn Sie Rich-Text-Eingaben zulassen müssen (z.B. WYSIWYG-Editor), verwenden Sie eine Sanitization-Library:
import DOMPurify from 'dompurify'
// Nur sichere HTML-Tags und -Attribute erlauben
const cleanHtml = DOMPurify.sanitize(userInput, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'br'],
ALLOWED_ATTR: ['href'],
})
Nie eigene Sanitization schreiben — verwenden Sie bewährte Libraries wie DOMPurify oder sanitize-html.
Linie 5: Sichere Cookie-Attribute
Schützen Sie Cookies vor Diebstahl durch XSS:
Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Strict
| Attribut | Schutz |
|---|---|
| HttpOnly | Cookie nicht per JavaScript lesbar |
| Secure | Nur über HTTPS gesendet |
| SameSite=Strict | Nicht bei Cross-Site-Requests gesendet |
Linie 6: Trusted Types (modern)
Trusted Types sind ein neuerer Browser-Mechanismus, der DOM-XSS auf API-Ebene verhindert:
Content-Security-Policy: require-trusted-types-for 'script'
Der Browser blockiert dann jeden Versuch, nicht-vertrauenswürdige Strings in unsichere DOM-Senken einzufügen.
XSS in der Praxis erkennen
Manuelle Tests
Probieren Sie typische XSS-Payloads in Eingabefeldern und URL-Parametern (z.B. Script-Tags, Event-Handler in HTML-Elementen, javascript:-URIs). Wenn ein Alert-Fenster erscheint, ist die Anwendung verwundbar.
Automatisierte Tools
| Tool | Typ | Kosten | |---|---|---| | OWASP ZAP | Active Scanner | Kostenlos | | Burp Suite | Proxy + Scanner | Community: kostenlos | | Nuclei | Template-Scanner | Kostenlos | | WarDek | Automatisierter Website-Scan | Kostenlos (Basic) |
Checkliste: XSS-Schutz
- ☐ Output Encoding in allen Templates aktiv
- ☐ Framework-Escape-Bypass nicht mit Benutzerdaten verwendet
- ☐ Input-Validierung serverseitig implementiert
- ☐ Content Security Policy gesetzt
- ☐ Cookies mit HttpOnly, Secure, SameSite
- ☐ DOMPurify für Rich-Text-Eingaben
- ☐ Regelmäßige XSS-Scans (monatlich)
- ☐ Entwickler geschult zu XSS-Prävention
Fazit
XSS-Schutz erfordert mehrere Verteidigungslinien — keine einzelne Maßnahme reicht aus. Die Kombination aus Output Encoding, CSP, Input-Validierung und sicheren Cookies macht Ihre Anwendung robust gegen die häufigsten Angriffsvektoren. Testen Sie regelmäßig, denn neue Code-Änderungen können neue XSS-Lücken einführen.
Scannen Sie Ihre Website kostenlos mit WarDek — OWASP, NIS2, DSGVO, AI Act Compliance in einem Scan.