dedlfix: Gefahren beim Kontextwechsel: Variablen in der URL die der User

Beitrag lesen

Hi!

In einem Formular wird eine Eingabe des Users durch die URL an ein PHP Script gesendet. Dort angekommen wird sie schließlich auf der Seite ausgelesen. MEine Frage ist nun, mit welchen Maßnahmen schütze ich mich dagegen, dass ein User irgendeinen Script über das Formular ausführt? Angenommen er sendet irgendwie sowas: <script>[... hier wird meine Seite gehackt] </script>.

Wo findet das Ausführen statt? Im Browser. Also muss der Browser die Daten so erhalten, dass er sie nicht als Anweisung interpretiert. Das lässt sich dadurch erreichen, dass die <http://de.selfhtml.org/html/allgemein/zeichen.htm#html_eigene@title=HTML-eigenen Zeichen> maskiert werden. Wenn also ein &lt; statt eines < in den an den Browser ausgelieferten Daten steht, wird er das nachfolgende script nicht als Anweisung ansehen sondern es es lediglich als Buchstaben auf dem Bildschirm anzeigen. Das sieht zwar doof, wenn man das auf der Seite sieht, ist aber harmlos. Du bist mit der HTML-gerechten Behandlung der Daten nicht gegen unsinnigen Inhalt geschützt, aber gegen dessen Ausführen.

Zur sicherung habe ich die variable, gleich nachdem sie im PHP_Script empfangen wird mit htmlspecialchars() versehen. Also so:
$variable=htmlspecialchars($_GET['variable'], ENT_QUOTES);

Das ist der falsche Zeitpunkt. Die HTML-kodierung nützt dir nur etwas im HTML-Kontext. Der ist aber nicht jetzt sondern erst irgendwann später, wenn überhaupt.

später wird sie dann so im Browser mir $variable ausgebeben.

Erst zu diesem Zeitpunkt solltest du die HTML-Behandlung vornehmen.

Im Anderen Fall übergebe ich sie wieder an eine URL:
header("LOCATION: testscript.php?variable=$variable");

Hier hast du keinen HTML-Kontext sondern eine URL vorliegen. Für URLs haben andere Zeichen eine Sonderbedeutung, weswegen du hier eine URL-Kodierung benötigst.

Wenn in $variable ein & enthalten ist - und das wird passieren, weil es beispielsweise bei &lt; vorkommt, so wird das beim Lesen des Querystrings als Ende des Wertes angesehen. Dein Wert wird also vorzeitig abgeschnitten und der folgende Rest stiftet auch noch Verwirrung. Die URL-kodierung sorgt jedoch dafür, dass unter anderem das & URL-gerecht notiert wird und somit die Eindeutigkeit zwischen & als Inhaltsbestandteil und & als gewolltem Trennzeichen gesichert ist.

Wenn du jedoch nun einfach dahergehst und noch die URL-Kodierung zu deiner htmlspecialchars-Behandlung hinzufügst, so bist zu war auf der sicheren Seite, jedoch bekommt der Empfänger, der die URL liest, nun einen HTML-kodierten Wert. Das ist normalerweise ungünstig, weil er nun einen bereits kodierten Wert vorliegen hat, aber andererseits aus anderen Quellen unkodierte Daten bekommt und nun aufpassen muss, wann noch welche Behandlung vorzunehmen ist. Abgesehen davon, kann es sein, dass die Daten nun gar nicht in den bereits vorbereiteten Kontext ausgegeben werden, sondern in einen anderen, was dann zunächst eine Dekodierung aus dem alten Zusatand und eine anschließende Kodierung für das neue Medium erfordert. Liest sich verworren? Nunja, das ist der Code am Ende auch, wenn man zu früh behandelt. Deshalb ist es besser, nur mit Rohdaten zu arbeiten und erst beim Übergang in einen anderen Kontext die dafür notwendige Behandlung vorzunehmen.

Hinzu kommen nun noch die fachlichen Anforderungen, also dass Werte je nach Anforderung der Anwendung auf bestimmte Inhalte kontrolliert werden oder verarbeitet werden müssen. Auch hierfür ist es günstiger, mit Rohdaten arbeiten zu können.

Ist mein Vorgehen so sicher?

Du musst dich immer fragen: Welche Zeichen haben in einer bestimmten Situation eine besondere Bedeutung? Und wie notiert man sie, damit sie diese Bedeutung nicht haben, wenn das nicht gewünscht ist?

Oder auch anders betrachtet: Die Syntaxregeln eines bestimmten Systems schreiben vor, wie Werte notiert werden müssen. Halte dich an diese Regeln, um keinen Syntaxfehler oder eine Fehlinterpretation zu bekommen.

Besonderes Augenmerk muss dabei auf "verdeckte Werte" gelegt werden. Ein String in einem Programmcode ist offensichtlich. Wenn eine Maskierung vergessen wurde, wird der Syntaxfehler recht schnell auffallen. Ein Variableninhalt ist verdeckt, da sieht man nur den Variablennamen. Und wenn man nicht zufällig (oder besser gezielt) mit den Sonderzeichen als Eingabe testet, kommt das Versäumnis nicht gleich zum Vorschein.

Lo!