Was ist XSS und wie schützt man sich?
Autor: Redaktion Domeny.ForSale Veröffentlicht
Kurz erklärt: XSS (Cross-Site Scripting) ist eine Sicherheitslücke, durch die der Browser nicht vertrauenswürdigen Code im Kontext der besuchten Website ausführt. Sie entsteht meist dann, wenn eine Anwendung Benutzerdaten als Bestandteil einer Seite oder als Code behandelt statt als einfachen Text. Entscheidend für den Schutz ist vor allem die sichere Ausgabe von Daten, nicht nur das Blockieren verdächtiger Eingaben.
Wie XSS funktioniert und was Angreifer tun können
Der Browser interpretiert HTML als Seitenstruktur und JavaScript als auszuführende Anweisungen. Fügt eine Anwendung ungeprüfte Inhalte an einer Stelle ein, an der sie als Code interpretiert werden, kann ein Angreifer das Verhalten der Seite bei anderen Benutzern beeinflussen. Solche Inhalte können aus einem Kommentar, einem Adressparameter, einem Profilnamen oder der Antwort eines externen Dienstes stammen.
Durch XSS ausgeführter Code läuft im Kontext der angegriffenen Website. Er kann zugängliche Daten auf der Seite auslesen, deren Inhalt verändern, ein gefälschtes Anmeldeformular anzeigen oder Aktionen mit den Berechtigungen des angemeldeten Benutzers ausführen. Die tatsächlichen Folgen hängen von den Funktionen der Anwendung und den eingesetzten Schutzmaßnahmen ab.
Das bedeutet nicht automatisch, dass der Server oder der gesamte Computer übernommen wird. Das Problem betrifft vor allem das Vertrauen des Browsers in Code, den die jeweilige Website ausführt. Benutzer können die richtige Adresse öffnen und trotzdem auf einer Seite mit schädlichen Inhalten landen.
Die drei am häufigsten beschriebenen Formen von XSS
Die Einteilung hilft festzustellen, woher die gefährlichen Inhalte stammen und an welcher Stelle die Anwendung sie verarbeitet:
- Stored XSS, also gespeichertes XSS: Inhalte werden gespeichert, etwa in einer Kommentardatenbank. Das Problem tritt auf, wenn die Anwendung sie anderen Personen auf unsichere Weise anzeigt. Das Speichern in der Datenbank allein ist noch keine Sicherheitslücke.
- Reflected XSS, also reflektiertes XSS: Die Anwendung übernimmt Daten aus einer Anfrage, etwa einen Suchbegriff aus der URL, und fügt sie ohne ausreichenden Schutz in die Antwort ein. Angreifer können versuchen, ihr Opfer zum Öffnen eines präparierten Links zu bewegen.
- DOM-based XSS: Die unsichere Verarbeitung findet in JavaScript statt, das im Browser läuft. DOM steht für das Dokumentenobjektmodell, also die Darstellung der Seite, die Skripte auslesen und verändern können.
Diese Begriffe schließen sich nicht immer gegenseitig aus. „Gespeichert“ und „reflektiert“ beschreiben hauptsächlich, auf welchem Weg die Daten eingebracht werden. „DOM-based“ bezeichnet dagegen den Ort der unsicheren Verarbeitung. Auch in einer Datenbank gespeicherte Inhalte können zu DOM-based XSS führen.
Einfaches Beispiel: Text wird als HTML behandelt
Angenommen, eine Anwendung zeigt einen Benutzernamen an. Führe das folgende Beispiel ausschließlich in deiner eigenen Testumgebung oder dort aus, wo du ausdrücklich dazu berechtigt bist:
const name = '<img src="x" onerror="alert(\'XSS-Test\')">';
const element = document.querySelector('#begruessung');
element.innerHTML = name;
Die Eigenschaft innerHTML weist den Browser an, den Wert als HTML zu interpretieren. Wird das Bild nicht geladen, kann die Fehlerbehandlung alert auslösen und damit ein Meldungsfenster anzeigen. Das demonstriert die Ausführung von Code, nicht den Diebstahl von Daten. Zusätzliche Schutzmaßnahmen des Browsers oder der Website können die Ausführung blockieren.
Soll der Name als einfacher Text erscheinen, ist dies die richtige Lösung:
const name = '<img src="x" onerror="alert(\'XSS-Test\')">';
const element = document.querySelector('#begruessung');
element.textContent = name;
Die Eigenschaft textContent zeigt die angegebene Zeichenfolge an, ohne ein Bild zu erzeugen oder die darin enthaltene Anweisung auszuführen. Der Unterschied ist grundlegend: Daten bleiben Daten. Man muss nicht erraten, welche Wörter oder Tags gefährlich sein könnten.
So schützt du eine Anwendung vor XSS
Stimme den Schutz darauf ab, wo die Daten verwendet werden. Bei der Ausgabekodierung werden Sonderzeichen so dargestellt, dass sie nicht als Syntax interpretiert werden. Für Text in HTML gelten andere Regeln als für einen Attributwert, eine URL oder einen Abschnitt mit JavaScript. Nur die spitzen Klammern < und > zu ersetzen, schützt nicht in all diesen Situationen.
Verwende für die Ausgabe von einfachem Text sichere Template-Mechanismen und Schnittstellen wie textContent. Die automatische Kodierung eines Frameworks hilft, lässt sich aber durch eine Funktion umgehen, die unverarbeitetes HTML einfügt. Solche Ausnahmen müssen gesondert geprüft werden.
Wenn Benutzer tatsächlich Formatierungen mit HTML benötigen, verwende eine aktiv gepflegte Bibliothek zur Bereinigung, etwa DOMPurify. Diese Bereinigung, auch Sanitization genannt, entfernt unzulässige Elemente und Attribute nach festgelegten Regeln. Ein selbst gebauter Filter mit einigen regulären Ausdrücken bietet keinen gleichwertigen Schutz.
Validierung, also die Prüfung auf ein zulässiges Datenformat, bleibt sinnvoll: Ein Altersfeld sollte eine Zahl akzeptieren, eine Linkadresse ein erlaubtes URL-Schema verwenden. Sie ersetzt jedoch nicht die sichere Ausgabe. Auch nur das Formular abzusichern reicht nicht aus, denn Daten können auf anderen Wegen in die Anwendung gelangen.
Zusätzliche Schutzschichten begrenzen die Folgen von Fehlern. Mit CSP (Content Security Policy) lassen sich Regeln für die Ausführung von Skripten festlegen. Ihre Wirksamkeit hängt jedoch von der Konfiguration ab. Das Attribut HttpOnly verhindert, dass JavaScript ein Cookie ausliest. Es verhindert aber nicht jede Aktion, die schädlicher Code innerhalb einer aktiven Sitzung ausführen kann.
So beginnst du mit der Prüfung deiner eigenen Website
Verfolge die Daten eines einzelnen Feldes von der Eingabe bis zu jeder Stelle, an der sie angezeigt werden. Ein Kommentar kann unter einem Artikel sicher ausgegeben werden, im Moderationsbereich oder in der Vorschau einer Benachrichtigung dagegen unsicher. Prüfe außerdem die Verwendung von innerHTML und von Funktionen, mit denen sich die automatische Kodierung umgehen lässt.
Teste anschließend in einer isolierten Umgebung, ob der eingegebene Inhalt als Text erscheint oder die Seitenstruktur verändert. Ergänze nach der Korrektur einen Regressionstest, der erkennt, wenn diese Daten erneut als HTML behandelt werden.
Siehe auch: Was ist 2FA?
