dedlfix: register_globals = Off

Beitrag lesen

echo $begrüßung;

$rows = mysql_query("SELECT * FROM ".$prefix."log where kat = $katid2 && free = 0");
[...] aber die Variable $katid2 wird dank Register-Globals auf $_GET['katid2'] gesetzt und im Programm nirgendwo auf gültige Werte geprüft, geschweige denn für den SQL-String entsprechend escaped.
Was das heißt? Dass das ein dickes Sicherheitsloch ist, über welches man nach belieben an deiner Datenbank rumspielen (Daten auslesen, manipulieren, löschen) kann.

Prinzipiell stimme ich der Nicht-Empfehlung für dieses Script zu, aber dieses Argument kann ich so nicht stehen lassen. PHP und MySQL lassen pro mysql_query()-Aufruf nur ein Statement zu und ein SELECT-Statement kann man nicht so verbiegen, dass man damit Daten ändern oder löschen kann.

Du wolltest vermutlich diese Sicherheitslücke als allgemeine Lücke beschreiben, und nicht nur auf dieses SELECT-Statement bezogen sehen. Dann stimmt die Warnung wieder, denn im Admin-Script sieht man UPDATE- und DELETE-Statements, die ebenfalls die Eingabedaten nicht MySQL-gerecht aufbereiten. Stattdessen wird da htmlspecialchars() verwendet, eine in diesem Kontext völlig unbrauchbare Methode.

Da der Autor auf register_globals=on setzt, wird er sicher auch auf eingeschaltete Magic Quotes gesetzt haben. Das ist ein gut gemeintes PHP-Feature, aber ebenfalls nicht wirklich verwendbar, denn es manipuliert die Eingabedaten ohne Rücksicht auf das später verwendete konkrete Ausgabemedium. Aber immerhin verhindert es einfache SQL-Injection-Angriffe, das jedoch mit einigem Kollateralschaden (Betreibt man ein Affenformular mit eingeschalteten MQ freut man sich bei jeder Korrekturrunde besonders über die Vermehrung der \ vor eingegebenen " oder ').

Genug gewarnt, doch wie macht man es richtig? Grundsätzlich: Wenn Werte in einen bestimmten Kontext gebracht werden sollen, müssen sie dem Kontext gemäß behandelt werden. Und zwar nur für diesen und keinen anderen (vielleicht irgendwann später mal verwendeten) Kontext.
Für MySQL gibt es mysql_real_escape_string() oder mysqli::escape_string() oder Prepared Statements.
Für HTML ist htmlspecialchars() gedacht.

Gelegentlich muss man Eingabedaten aus einer Transportsicherung befreien, und bei PHP gegebenenfalls die Magic Quotes entfernen. Auf alle Fälle sollte man die Eingabedaten einer Plausibilitätsprüfung unterziehen. Möchte ich eine E-Mail-Adresse eingegeben wissen, darf darin beispielsweise kein Zeilenumbruch vorkommen. Ein Zahlenwert darf auch keine Buchstaben enthalten (Exponentialdarstellung und Hex-Werte mal außen vor gelassen).

echo "$verabschiedung $name";