Glossar · Sicherheit
Cross-Site-Scripting (XSS)
Englisch: Cross-site scripting
Auch genannt: XSS, Cross Site Scripting, Stored XSS, Reflected XSS
Definition
Eine Schwachstelle, bei der fremde Eingaben im Browser eines anderen Nutzers als Skript ausgeführt werden, sodass ein Angreifer in dessen Namen handeln kann.
Cross-Site-Scripting (XSS) entsteht, wenn eine Anwendung Eingaben eines Nutzers ohne korrektes Encoding in eine Seite übernimmt, sodass der Browser sie als HTML oder JavaScript statt als Text behandelt. Das Skript läuft dann mit der Session des Opfers auf der verwundbaren Website: Es kann Seitendaten lesen, Requests im Namen des Nutzers senden oder verändern, was er sieht. In den OWASP Top 10 2021 ist es unter A03 Injection eingeordnet.
Die drei Arten
- Stored (persistent). Die Payload wird gespeichert (ein Kommentar, ein Profilname, ein Support-Ticket) und an alle ausgeliefert, die sie ansehen. Meist die gravierendste Variante.
- Reflected. Die Payload steckt im Request, oft in einem URL-Parameter wie einem Suchbegriff, und wird direkt in der Response zurückgegeben.
- DOM-based. Clientseitiges JavaScript liest vom Angreifer kontrollierte Daten (zum Beispiel
location.hash) und schreibt sie über eine unsichere Senke wieinnerHTMLin die Seite.
Was ein Tester prüft
Setzen Sie einen harmlosen Marker in jedes Feld, das später angezeigt wird (Ihnen, anderen Nutzern, Admins im Backoffice), und prüfen Sie, ob er als Text oder als aktives Markup zurückkommt. Eine automatisierte Prüfung in Playwright, nur für autorisierte Tests:
import { test, expect } from '@playwright/test';
test('comment body is rendered as text, not HTML', async ({ page }) => {
const probe = '<img src=x onerror="window.__xssProbe=1">';
await page.goto('/posts/1');
await page.getByLabel('Comment').fill(probe);
await page.getByRole('button', { name: 'Post comment' }).click();
// Escaped output shows the literal characters on screen
await expect(page.getByText(probe)).toBeVisible();
// and the handler never ran
expect(await page.evaluate(() => (window as any).__xssProbe)).toBeUndefined();
});
Prüfen Sie auch Ausgabekontexte jenseits von reinem HTML: Werte in Attributen, in Inline-Skripten, in URLs (javascript:-Links) und in Rich-Text-Editoren, denn jeder Kontext braucht ein anderes Encoding.
Zu prüfende Schutzmaßnahmen
- Output Encoding als Standard. Moderne Frameworks (React, Angular, Vue) escapen Text automatisch; suchen Sie nach den Hintertüren wie
dangerouslySetInnerHTML,v-htmloderinnerHTML. - HTML-Sanitizing für Funktionen, die tatsächlich Markup akzeptieren.
- Ein Content-Security-Policy-Header, der Inline-Skripte blockiert, als zweite Verteidigungslinie.
HttpOnly-Session-Cookies, damit ein erfolgreicher XSS-Angriff das Session-Cookie nicht einfach auslesen kann.
Testen Sie niemals Systeme, die Ihnen nicht gehören oder für die Sie keine schriftliche Testerlaubnis haben.