Das hatte ich hier schon mal irgendwo länglich geschrieben, finde es aber gerade nicht.
Dann hätte ich die Daten doch schon bereinigt in der Datenspeicherung drinnen
Du weißt aber nie, was du mit den Daten noch machen willst. Du willst Daten bei der Speicherung immer im allgemeinst möglichen Format speichern. Was, wenn du die Daten statt direkt ins HTML auszugeben, mal als JSON ausgeben möchtest? Oder als CSV?
Ich würde soweit gehen und sagen, dass Speicherung von Daten in einer maskierten Form -- zumindest am Primärspeicherort zumindest; in spezialisierten Caches wäre es mitunter sinnvoll -- ein kaputtes Datenmodell aufweist.
Auch
philosophisch macht es viel mehr Sinn bei der Ausgabe zu maskieren: das
Problem ist in fast allen Fällen das naive Interpolieren von Kontext und Daten. Bei XSS ist der Kontext HTML und die Daten Nutzereingaben. Das Problem tritt immer dann auf, wenn die Zielsprache keine Unterscheidung dafür bieten kann. HTML kann es nicht, weil es sowieso eine wenig ausdrucksstarke Sprache ist. Hingegen SQL -- oder präziser gesagt: SQL Driver -- können es via Prepared Statements zumindest bedingt. Bei LIKE-Anfragen mit variablem Wildcard hast du dann dasselbe Problem wie vorher bei SQL Injections trotz Prepared Statements.
Maskieren hängt also immer von der Ausgabeart ab. Ausgabe zwischen HTML-Tags ist nicht dasselbe wie Ausgabe in einem HTML-Attribut. In Letzterem musst du selbst Quotes maskieren. Ausgabe in HTML4 ist nicht dieselbe Ausgabeart wie HTML5. Selbst SQL-Queries in UTF-8 sind nicht dieselbe Ausgabeart wie SQL-Queries in einer anderen Zeichenkodierung. Da gab es in der Vergangenheit durchaus Sicherheitslücken in SQL Drivern, weil die Maskierung das nicht miteinkalkuliert hat.
Um den Punkt von oben mit dem kaputten Datenmodell nochmal aufzugreifen: ich finde es deswegen kaputt, weil du die sehr spezifische Annahme machst, dass die Daten nur in HTML5, da nur zwischen Tags und dann noch in Kodierung X ausgegeben werden.
PS: Ich sollte irgendwann mal einen Blogpost darüber schreiben