dedlfix: SQL-Injection

Beitrag lesen

echo $begrüßung;

PS: derzeit versuche ich mit Select * FROM Tabelle WHERE ID='addslashes(htmlentities(htmlspecialchars($_GET['ID'])))' Codeeinspeisung zu verhindern. Ist dies der richtige Weg?

Im Prinzip wurde deine Frage ja schon beantwortet, aber zu diesem Konstrukt möchte ich noch ein paar Worte verlieren.

Bei der Ausgabe von Werten ist es wichtig, den jeweiligen Kontext zu beachten, in den die Werte ausgegeben werden. Du hast hier ein SQL-Statement und kein HTML vorliegen, deswegen sind alle Behandlungen für den HTML-Kontext fehl am Platz. Dass du später mal den Datenbankinhalt nach HTML ausgeben willst, interessiert an dieser Stelle überhaupt nicht. Zum einen, weil du nicht wissen kannst, ob du später die Daten nicht mal in einen anderem Kontext ausgeben willst, zum anderen, weil durch die verunstalteten Zeichen Stringfunktionen in der Datenbank nicht mehr richtig arbeiten können.

In einigen Kontexten (beispielsweise SQL, HTML, XML) werden Daten und Code gemeinsam übertragen. Man nimmt Maskierungen deshalb vor, um zu unterscheiden, ob es sich bei bestimmten Zeichen um Code oder Daten handelt.

Der Grundsatz lautet deshalb: Daten _immer_ und _nur_ kontextabhängig behandeln.

htmlentities() berücksichtigt auch die Zeichen, die htmlspecialchars() behandelt. Wenn du beide Funktionen schachtelst, erhältst du eine doppelte Maskierung. Es ist in den meisten Fällen ausreichend, htmlspecialchars() zu verwenden (natürlich nur bei der Ausgabe in einen HTML-Kontext). Die Fälle, in denen htmlentities() benötigt wird, will man nicht haben.

Neben den unbedingt zu berücksichtigenden HTML-eigenen Zeichen <, >, & und " braucht man keine weiteren Maskierungen, wenn man für das Dokument eine passende Kodierung gewählt hat. (Bitte beachte bei dem Thema "Zeichen" die Begrifflichkeiten. Ein Vermischen stiftet regelmäßig Verwirrung und ist für das Verständnis des Themas nicht hilfreich.) Verwendest du die Zeichenkodierung ISO-8859-1, kannst du zwar deutsche Umlaute damit abbilden und dir erscheint das vielleicht ausreichend. Doch irgendwann gibt mal jemand ein Zeichen außerhalb von ISO-8859-1 ein, und dann machen einige Browser daraus eine Ersatzdarstellung &#xxxx;. Diese Ersatzdarstellung nehmen sie aber nicht für ein normales &, und sie unterscheidet sich auch nicht von einer händischen und beabsichtigten Eingabe solch einer Zeichensequenz. Welche Sequenz soll nun bei der Ausgabe durchgelassen werden und welche nicht? Anders gefragt: Welche Sequenz ist bereits HTML-kodiert und welche muss noch so behandelt werden, damit sie so wie beabsichtigt erscheint und nicht statt ihrer ein Zeichen angezeigt wird?

Als Ausweg aus diesem Dilemma ist die konsequente Verwendung der Zeichenkodierung UTF-8 eine Lösung. Damit lassen sich praktisch sämtliche bekannte Zeichen kodieren und der Browser braucht keine Ersatzdarstellungen zu verwenden. Leider ist für PHP erst ab Version 6 eine Unterstützung für Unicode und UTF-8 geplant. Die derzeit vorhandene mbstring-Extension steht nicht überall zur Verfügung. Diese Einschränkung kommt nur dann zum Tragen, wenn man mit PHP Strings bearbeiten muss (z.B. kürzen, sortieren). Wenn man sie nur durchreichen lässt, gibt es im Prinzip keine Probleme.

Zurück zu htmlentities(). Diese Funktion braucht man nur, wenn man Daten vorliegen hat, die sich in der von der HTML-Seite verwendeten Kodierung nicht transportieren lassen. Doch wo sollen diese Zeichen herkommen? Bei der Eingabe werden sie vom Browser verunstaltet. In der Datenbank können sie nur dann stehen, wenn sie anderweitig da hinein gelangt sind. Bleiben noch Inhalte aus anderen/fremden Quellen übrig, die man direkt anzapft. In einem solchen Fall sollten dann in einer Einzelfallentscheidung die konkreten Umstände berücksichtigt werden.

Zusammenfassung:

  • keine HTML-Kodierung für den SQL-Kontext verwenden, bzw. obigen generellen Grundsatz beherzigen.
  • angemessene Kodierung verwenden, htmlentities() ad acta legen, htmlspecialchars() für den HTML-Kontext verwenden.

echo "$verabschiedung $name";