Cookies für Statistik und Werbung
Wir setzen Cookies für Statistik und Werbung ein, beides geht an Google. Wenn du ablehnst, ändert sich für dich sichtbar nichts.Zur Datenschutzseite
Füge Text ein und bekomme ihn zurück, wobei die Zeichen, die verändern, wie ein Dokument geparst wird, durch ihre Ersatzschreibweisen ersetzt sind. Das ist der Handgriff, der aus einem Text, den jemand anderes geschrieben hat, Inhalt statt Struktur macht — und die Stelle, an der eine ausgelassene Ersetzung aus einem Kommentarfeld ein Sicherheitsproblem macht. Die Rechnung passiert in dieser Seite, hochgeladen wird nichts.
Wo es läuft
Es wird nichts hochgeladen, weil es keine Datei gibt — gerechnet wird in dieser Seite.
Keine Warteschlange, kein Konto
Es antwortet so schnell, wie dein Rechner es hergibt, und fragt nie, wer du bist.
So oft du willst
Nichts wird gezählt und nichts begrenzt — noch einmal zu antworten kostet uns nichts.
Ein HTML-Parser interessiert sich für sehr wenige Zeichen. Ein spitzes Klammernpaar beginnt und beendet ein Tag, ein kaufmännisches Und beginnt eine Zeichenreferenz, und in Attributwerten beenden das doppelte und das einfache Anführungszeichen den Wert. Das sind fünf Zeichen, und alles andere ist für den Parser gewöhnlicher Inhalt.
Deshalb maskiert die sparsame Einstellung genau diese fünf und sonst nichts. Ein Kodierer, der aus jedem Umlaut eine Entität macht, ist nicht sicherer — er erzeugt nur eine Ausgabe, die vier- bis fünfmal so lang und für Menschen unlesbar ist, während er gegen genau dieselben Angriffe schützt wie die kurze Variante.
Wer selbst ersetzt, muss mit dem `&` anfangen. Kommt es später an die Reihe, hat der Kodierer bereits eigene Entitäten erzeugt, deren `&` er dann noch einmal maskiert — aus einem `<` wird `<` und daraus `&lt;`, und die Seite zeigt den Text `<` an statt eines spitzen Klammernpaars.
Das ist der mit Abstand häufigste Fehler in handgeschriebenen Escape-Funktionen und einer der wenigen, die man an der Ausgabe sofort erkennt: Wenn im Ergebnis `&` vor anderen Entitätsnamen steht, ist die Reihenfolge falsch. Dieses Werkzeug arbeitet die Ersetzung in einem Durchgang ab, das Problem kann hier also nicht entstehen.
Zwischen zwei Tags reichen drei Ersetzungen: kleiner-als, größer-als und das kaufmännische Und. In einem Attributwert kommen die Anführungszeichen dazu, denn dort beendet ein doppeltes Anführungszeichen den Wert, und was danach steht, liest der Parser als weiteres Attribut — der klassische Einstieg, um ein `onmouseover` in ein fremdes Tag zu schmuggeln.
Besonders zäh wird es bei unquotierten Attributwerten, die HTML erlaubt: Dort beendet schon ein Leerzeichen den Wert, und Maskieren allein reicht nicht mehr. Die praktische Regel lautet, Attributwerte immer in Anführungszeichen zu setzen und alle fünf Zeichen zu maskieren; die Einstellung hier tut genau das.
Die zweite Einstellung schreibt zusätzlich jedes Zeichen jenseits von ASCII als numerische Referenz, aus `ü` wird also `ü`. Für die Sicherheit bringt das nichts, für die Lesbarkeit ist es ein Verlust — es hilft ausschließlich dort, wo irgendein Glied der Kette kein UTF-8 verträgt.
Solche Glieder gibt es noch: alte E-Mail-Vorlagen, Exporte in Systeme mit fest verdrahteter Latin-1-Annahme, gelegentlich ein Datenbankfeld mit falscher Kollation. Wenn Umlaute unterwegs zu Fragezeichen oder zu einem Ä-Doppelzeichen werden, ist die numerische Schreibweise ein belastbarer Umweg. Wo die Kette sauber UTF-8 spricht, ist sie überflüssiges Gewicht.
Maskieren schützt an genau einer Stelle: beim Einsetzen in HTML. Es ist keine Eingabeprüfung und ersetzt keine. Wer beim Speichern maskiert statt beim Ausgeben, hat später Daten in der Datenbank, die in einer JSON-Antwort, einer CSV-Ausgabe oder einer E-Mail als `&` auftauchen — an Orten also, wo HTML nie im Spiel war.
Die Reihenfolge, die funktioniert, ist umgekehrt: unverändert speichern und beim Rendern für das jeweilige Ziel maskieren. Dieselben Daten gehen dann korrekt in HTML, in JSON und in eine Nur-Text-Mail, jeweils mit den Regeln, die dort gelten — und niemand muss raten, in welchem Zustand ein Feld gerade ist.
HTML kennt benannte Referenzen wie `&`, dezimale wie `&` und hexadezimale wie `&`. Alle drei bezeichnen dasselbe Zeichen, und ein Parser akzeptiert alle drei. Dieses Werkzeug erzeugt die benannten für die fünf entscheidenden Zeichen, weil die im Quelltext lesbar sind, und numerische für alles darüber.
Beim Lesen fremder Ausgaben begegnen einem alle drei gemischt, oft in derselben Datei, weil verschiedene Bausteine sie erzeugt haben. Das ist kein Fehler und kein Hinweis auf ein Problem — es sagt nur, dass an dem Dokument mehr als ein Werkzeug beteiligt war.
Für das einfache Anführungszeichen gibt es einen benannten Namen, `'`, aber er stammt aus XML und wurde erst mit HTML5 offiziell Teil von HTML. In HTML 4 war er nicht definiert, und sehr alte Parser geben ihn deshalb wörtlich aus statt ihn aufzulösen.
Die numerische Schreibweise `'` hat dieses Problem nie gehabt und funktioniert überall, weshalb sie bis heute in fast jeder Escape-Bibliothek die Vorgabe ist. Das ist einer der Fälle, in denen eine zwanzig Jahre alte Inkompatibilität die Konvention geprägt hat, obwohl der Anlass praktisch verschwunden ist.
Fast jede Template-Engine maskiert von sich aus — Twig, Blade, Jinja, JSX und Razor tun es standardmäßig. Wer denselben Wert vorher schon einmal durch eine Escape-Funktion geschickt hat, sieht in der fertigen Seite `<b>` als sichtbaren Text stehen statt eines fetten Worts.
Das Erkennungszeichen ist ein `&` unmittelbar vor einem anderen Entitätsnamen. Die Lösung ist immer, eine der beiden Stellen zu entfernen, und nie, am Ende einmal zusätzlich zu dekodieren — denn das entschärft dann auch die Maskierung, die dort hingehört, und macht aus einem Anzeigefehler ein Sicherheitsproblem.
Ein Wert, der in einen `<script>`-Block geschrieben wird, steht nicht mehr in HTML-Kontext, sondern in JavaScript-Kontext, und dort gelten andere Regeln. Ein maskiertes Anführungszeichen hilft dort nicht; umgekehrt kann eine Zeichenkette, die in HTML völlig harmlos ist, dort ein Skript beenden.
Dasselbe gilt für einen Wert in einem `href`, einem `style` oder einem `data-`-Attribut, das später ausgewertet wird. Jeder dieser Orte hat seine eigene Maskierung, und die richtige Frage ist nie „ist das maskiert“, sondern „ist es für den Ort maskiert, an dem es landet“. Dieses Werkzeug beantwortet den HTML-Fall.
Was in dieses Feld eingefügt wird, ist regelmäßig fremder Text — ein Nutzerkommentar, eine Support-Nachricht, eine Produktbeschreibung mit Namen darin. Weil die Ersetzung in der Seite passiert, findet keine Übermittlung an uns statt und damit keine Auftragsverarbeitung für diesen Inhalt.
Nachprüfbar ist das im Netzwerk-Panel des Browsers: Während der Benutzung geht keine Anfrage hinaus, die deine Eingabe trägt. Die Seite selbst kommt von einem CDN und die Website trägt Werbung, es gibt also Anfragen — sie kennen den Umstand deines Besuchs, aber nicht den Inhalt des Textfelds.
Wer bewusst Markup ausliefert — eine Newsletter-Vorlage, ein Redaktionssystem, in dem Autoren HTML schreiben dürfen — will genau nicht, dass die Tags zu Text werden. Dort ist Maskieren die falsche Antwort, und die richtige ist eine Bereinigung, die eine Liste erlaubter Elemente und Attribute durchsetzt.
Die Grenze verläuft an der Frage, ob das Markup Teil des Inhalts sein soll. Soll es das nicht, maskiert man vollständig; soll es das, braucht man einen Sanitizer und keine Escape-Funktion. Beides zu vermischen — ein bisschen maskieren, ein paar Tags durchlassen — ist der Weg, auf dem die meisten Lücken entstehen.
Nein. Die Ersetzung passiert in dieser Seite, in deinem Browser. Öffne das Netzwerk-Panel während du tippst, dann siehst du, dass keine Anfrage hinausgeht, die deine Eingabe trägt.
Weil sie für einen HTML-Parser gewöhnliche Zeichen sind und in einem UTF-8-Dokument nichts kaputtmachen. Wenn deine Verarbeitungskette kein UTF-8 verträgt, wähle die zweite Einstellung — dann werden sie als numerische Referenzen geschrieben.
An der Stelle, an der HTML zusammengesetzt wird, ja — das ist genau der Zweck. Es ersetzt aber keine Eingabeprüfung und gilt nicht für Werte, die in JavaScript, in einem href oder in einem CSS-Kontext landen. Dort gelten jeweils eigene Regeln.
Dann war der Text bereits maskiert und wurde ein zweites Mal maskiert. Das ist kein Fehler des Werkzeugs, sondern der Hinweis, dass an einer früheren Stelle in deiner Kette schon eine Escape-Funktion gelaufen ist — meist die deiner Template-Engine.
Nur das, was dein eigener Browser mitmacht. Es rechnet kein Server mit, der etwas zählen oder deckeln könnte; sehr große Eingaben lassen den Tab kurz nachdenken, und das ist die einzige Grenze.