hackatoll
Zur Lernplattform

Wissen › Cross-Site Scripting (XSS)

Cross-Site Scripting (XSS)

Fremder Code läuft im Browser anderer Nutzer — weil Ausgaben nicht kontextgerecht kodiert werden.

Injection Schweregrad: Hoch

Cross-Site Scripting entsteht, wenn eine Anwendung Daten in eine Seite schreibt, ohne sie für den jeweiligen Ausgabekontext (HTML, Attribut, JavaScript, URL) zu kodieren. Angreifer schleusen so aktiven Code ein, der im Browser anderer Besucher ausgeführt wird — inklusive eingeloggter Redakteure und Administratoren.

Wie der Angriff funktioniert

Varianten

Stored (persistent): Der Payload wird gespeichert (z. B. Kommentar, Profil, Formular-Einsendung) und bei jedem Seitenaufruf erneut ausgeliefert — am gefährlichsten, weil er alle Betrachter trifft.
Reflected: Der Payload steckt im Request (z. B. Suchparameter) und wird direkt in die Antwort gespiegelt — meist über einen präparierten Link verbreitet.
DOM-based: Clientseitiges JavaScript schreibt unsichere Werte ins DOM (innerHTML, document.write) — der Server sieht den Payload teils gar nicht.

Beispiel

Wird ein Nutzerwert ohne Kodierung ausgegeben, bleibt eingeschleustes Markup aktiv:

<!-- unsicher: roh ausgegeben -->
<div class="comment"><?= $comment ?></div>

<!-- sicher: kontextgerecht kodiert -->
<div class="comment"><?= htmlspecialchars($comment, ENT_QUOTES) ?></div>

Mögliche Auswirkungen

◆ In TYPO3 beachten

Worauf du in TYPO3 achten musst

TYPO3 ist hier gut aufgestellt — solange man die Standardmechanismen nicht aushebelt. Fluid kodiert HTML-Ausgaben standardmäßig automatisch. Die meisten XSS-Lücken in TYPO3-Projekten entstehen genau dort, wo dieses Escaping bewusst abgeschaltet wird.

Fluid escaped automatisch — verlasse dich darauf

{variable} in einem Fluid-Template wird automatisch HTML-kodiert. Für normale Textausgabe ist nichts weiter nötig. Der Fehler ist fast immer das bewusste Abschalten.

f:format.raw / |raw ist der Hauptverdächtige

<f:format.raw>{userInput}</f:format.raw> bzw. {userInput -> f:format.raw()} gibt den Wert UNkodiert aus. Nur auf vertrauenswürdige, bereits bereinigte Inhalte anwenden — nie auf Nutzereingaben.

<!-- gefährlich bei Nutzereingabe -->
<f:format.raw>{comment.message}</f:format.raw>

<!-- sicher: Standardausgabe (escaped) -->
{comment.message}

RTE-/HTML-Inhalte sanitizen, nicht roh ausgeben

Richtext-Felder dürfen HTML enthalten. Gib sie über f:format.html (parseFunc, serverseitig gefiltert) aus — nicht über f:format.raw. Für freie HTML-Eingaben eine Allowlist-Bereinigung (HTML-Sanitizer) einsetzen.

Backend/TCA: Eingaben am Rand prüfen

TCA-'eval' (z. B. trim, int, alphanum_x) begrenzt, was gespeichert wird. Das ersetzt aber kein Ausgabe-Escaping — XSS entsteht bei der Ausgabe, nicht bei der Eingabe.

GeneralUtility::_GP & Co. nie roh ins HTML

Request-Werte (GET/POST) immer über htmlspecialchars() bzw. Fluid kodieren, bevor sie ausgegeben werden — besonders in eigenen ViewHelpern und PHP-gerenderten Snippets.

Content-Security-Policy als zweite Verteidigungslinie

TYPO3 v11 bringt eine CSP-Unterstützung (Frontend/Backend) mit; ab v12 ausgebaut. Eine strikte CSP reduziert den Schaden, ersetzt aber korrektes Escaping nicht.

Schutzmaßnahmen

Interaktiv üben

In der Lernplattform kannst du diese Schwachstellenklasse an einer echten, isolierten TYPO3-Instanz nachvollziehen:

Weiterlesen

Jetzt interaktiv üben →