flawopen.com/Cross-Site Scripting
Cross-Site Scripting
Cross-Site-Scripting entsteht, wenn eine Seite Text eines Nutzers so einbindet, dass der Browser ihn als HTML oder JavaScript parst – und er bei anderen Nutzern mit der Autorität der Website läuft. Die Lösung ist überall dieselbe: jeden Wert für genau die Stelle kodieren, an die er geschrieben wird, die seltenen Felder, die HTML erlauben müssen, bereinigen und beides mit einer Content Security Policy absichern. Wählen Sie unten Ihre Sprache für die genauen APIs, anfälligen und korrigierten Code und die CI-Regeln, die das Problem finden.
Einfache Erklärung (ELI5)
Eine Zeitung druckt Leserbriefe auf ihren eigenen Seiten. Ein Leser schickt einen Brief, der genau wie eine Mitteilung der Redaktion gesetzt ist: „Abonnenten: Rufen Sie diese Nummer an und nennen Sie Ihre Kartendaten zur Verlängerung.“ In der Schrift der Zeitung gedruckt, vertrauen die Leser ihm, als hätte die Redaktion ihn verfasst. XSS heißt: Eine Website druckt den Text eines Besuchers in ihre eigene Seite, und der Browser behandelt ihn als Code der Website – mit deren Zugriff auf Ihr Konto. Escaping druckt jeden Leserbrief in einen deutlich markierten Zitatkasten, sodass keiner als Mitteilung der Redaktion durchgeht.
Kernkonzepte & Begriffe
- Cross-site scripting (CWE-79)
- Eine Webseite bindet nicht vertrauenswürdige Daten ein, ohne sie für den Browser zu neutralisieren. Markup oder Skript darin wird im Origin der Seite geparst und ausgeführt, mit Zugriff auf DOM, Cookies und APIs.
- Reflected, stored and DOM-based XSS
- Reflektiertes XSS gibt Request-Daten direkt in der Antwort zurück, meist über einen präparierten Link. Gespeichertes XSS legt den Wert ab und liefert ihn jedem Betrachter aus. DOM-basiertes XSS berührt den Server gar nicht: Client-JavaScript kopiert Daten aus der URL oder dem Speicher in einen Sink wie
innerHTML. - Contextual output encoding
- Jeder Ausgabekontext braucht seine eigene Kodierung: HTML-Entities für Elementtext und quotierte Attribute, JavaScript-String-Maskierung in Skripten, Prozentkodierung in URL-Parametern und eine Schemaprüfung für
hrefundsrc. Einen Wert in einem Skript nur HTML-zu-kodieren, reicht nicht. - Sanitizing vs encoding
- Kodieren zeigt Markup als Text. Müssen Nutzer Formatierung einreichen, das HTML durch einen Allowlist-Sanitizer schicken (DOMPurify, nh3 als Nachfolger von bleach, OWASP Java HTML Sanitizer, HtmlSanitizer, ammonia), der erlaubte Tags behält und Skripte, Event-Handler und
javascript:-URLs entfernt. - Content Security Policy (CSP)
- Ein Antwort-Header, der dem Browser sagt, welche Skripte laufen dürfen. Ein Nonce-basiertes
script-srcohne'unsafe-inline'blockiert die meisten eingeschleusten Skripte, selbst wenn ein Kodierfehler durchrutscht, undrequire-trusted-types-for 'script'sichert die DOM-Sinks ab.
Schritt-für-Schritt Angriffsablauf
Nicht vertrauenswürdiger Text erreicht eine Seite
Ein Suchbegriff, ein Profilfeld, ein Kommentar, ein URL-Fragment oder eine API-Antwort wird eingebunden, wenn die Seite auf dem Server gebaut oder im Browser aktualisiert wird.
Er wird ohne passende Kodierung geschrieben
Das Template-Escaping ist abgeschaltet, der Wert landet in einem Skript- oder URL-Kontext, den HTML-Maskierung nicht abdeckt, oder Client-Code weist ihn innerHTML zu. Der harmlose Testwert <img src=x onerror=alert(1)> übersteht das unverändert.
Der Browser parst ihn als Code
Der Browser des Opfers baut ein echtes <img>-Element und löst onerror aus oder führt beim Klick einen javascript:-Link aus.
Das Skript handelt als die Website
Es läuft mit dem Origin der Website: Es kann die Seite lesen, die APIs mit den Cookies oder Tokens des Opfers aufrufen, ändern, was der Nutzer sieht, und in seinem Namen Formulare absenden.
XSS-Leitfäden nach Sprache
Checkliste für Engineering & Systemsicherheit
- Jede Seite über eine Template-Engine mit aktivem Autoescaping rendern und jeden Ausstieg prüfen (
|safe,Html.Raw,dangerouslySetInnerHTML,raw,unsafe { },{!! !!}). - Für den genauen Kontext kodieren: HTML-Text und quotierte Attribute, JavaScript-Strings, URL-Parameter; nie HTML oder JavaScript per String-Verkettung bauen.
- Nutzergeliefertes HTML an der Stelle, an der es gerendert wird, mit einem gepflegten Allowlist-Sanitizer bereinigen.
- In nutzergelieferten URLs nur
httpundhttpszulassen, bevor siehref,srcoder eine Navigation erreichen. - Eine Nonce-basierte Content-Security-Policy ohne
'unsafe-inline'senden, dazuX-Content-Type-Options: nosniff. - Session-Tokens in
HttpOnly-,Secure- undSameSite=Lax-Cookies statt inlocalStoragehalten.