Es ist im wesentlichen egal, wie die Daten in das lokale Programm kommen - GET, POST, COOKIE oder Request-Parameter spielt kaum eine Rolle. Es ist jedoch wesentlich, dass diese Variablen a) keine Variablen des lokalen Programmes unkontrolliert überschreiben können und b) dass der Übergang von solchen benutzerkontrollierten Variablen in lokale Variablen des Programmes nur nach einer Prüfung der Variablen auf legale Werte stattfindet. Das bedeutet:
-
Variablen mit vorgegebenen Werten aus einer Wertemenge ("Auswahlvariablen"), wie sie zum Beispiel aus einem <select> fallen:
Das Programm sollte ein lokales Array haben, das die möglichen Werte als Index eines Hash enthält:
$val = array( "wert1" => 1, "wert2" => 1, "wert3" => 1 );
Die Prüfung von $_GET["selectvar"] kann nun so aussehen:
$checkedvar = isset($val[$_GET["selectvar"]]) ? $_GET["selectvar"] : "default";
Wenn $_GET["selectvar"] einen in $val definierten Wert hat, dann wird dieser Wert nach $checkedvar übernommen. Hat man versucht, dem Programm einen vierten Wert unterzuschieben, dann wird $checkedvar auf "default" gesetzt. Das Programm arbeitet dann ausschliesslich mit $checkedvar. Auf diese Weise können dem Programm keine beliebigen Werte aus $_GET["selectvar"] untergeschoben werden.
-
Variablen, die eine bestimmte Form haben müssen, aber für die nicht die abgeschlossene Wertemenge aufgezählt werden kann ("Freitextvariablen mit Formvorschrift"):
Das Programm sollte eine oder mehrere Regex in einem Feld vorliegen haben:
$val = array( '/^[a-zA-Z ]+$/', '/^[0-9-]+$/' );
Die Prüfung kann nun so aussehen:
$checkedvar = "default"; if (isset($_GET["inputvar"])) { foreach ($val as $k => $v) { if (preg_match($v, $_GET["inputvar"])) { $checkedvar = $_GET["inputvar"]; break; } } }
Wenn $_GET["inputvar"] einen Wert hat, der auf eines der Muster in $val passt, wird dieser Wert in $checkedvar übernommen. Dazu müssen die Muster in $val natürlich vorne und hinten verankert sein (also mit ^ beginnen und $ enden), sonst kann man der Prüfung etwas unterschmuggeln. Passt kein Muster, hat $checkedvar hinterher den Wert "default". Das Programm arbeitet dann ausschliesslich mit $checkedvar. Auf diese Weise können dem Programm keine beliebigen Werte aus $_GET["selectvar"] untergeschoben werden.
-
Variablen, die eine numerische Form haben müssen.
Numerische Variablen können durch eine einfache Konvertierung erzwungen werden. Danach muss eine Überpruefung des Wertebereiches erfolgen:
$checkedvar = isset($_GET["numericvar"]) ? $_GET["numericvar"]+0 : 0;
Durch die Addition von 0 wird eine Konvertierung in eine Zahl erzwungen. Der Wert ist hinterher entweder Wert des numerischen Prefix von $_GET["numericvar"] oder 0. "123abc" wird also zu 123, "fasel" zu 0. Ein fehlender Wert wird durch das isset() ebenfalls zu 0.
-
Variablen, die Dateinamennatur haben.
Programme sollen oft Dateinamen, aber keine Pfadnamen annehmen. Eine Prüfung auf "/" im Dateinamen reicht oftmals als Sicherheitsprüfung aus. Zwingt man außerdem noch die Endung hinten dran, erschwert man die Ausnutzung von Sicherheitslücken zusätzlich, sollten dennoch welche vorhanden sein.
$checkedvar = "default"; if (isset($_GET["filenamevar"]) && !preg_match('=/=', $_GET["filenamevar"])) { $checkedvar = $_GET["filenamevar"] . ".ext"; }
-
Templatenamen
Templatenamen sind kein Spezialfall von Dateinamen oder Namen mit Formvorschrift, sondern ein Spezialfall von vorgegebenen Werten aus einer Liste und sollten wie der erste Fall behandelt werden.
-
Benutzerinput, der Tags enthalten kann
Cross Site Scripting Attacks sind Attacken, in denen eine Benutzereingabe aus einem Formular in die eigene Site als HTML, CSS oder anderer Formattext übernommen wird. Auf diese Weise kann der Benutzer eigene Elemente in unsere Website einbinden (etwa Bilder, Formulare oder Javascript von seiner Site), die einem Opfer dann als legitime Bestandteile unserer Site erscheinen und mit den Rechten unserer Site beim Opfer ausgeführt werden.
Die allgemein übliche Empfehlung, strip_tags() auf Benutzereingaben anzuwenden, ist nicht wirklich eine gute Idee. Vielmehr sollten alle (von außen kommenden) Variablen entsprechend dem Zielmedium vor der Weitergabe maskiert werden. Für Ausgabe im HTML-Kontext wird dazu htmlspecialchars() verwendet, für den Gebrauch in einem MySQL-Statement mysql_real_escape_string(). Für alle Subsysteme, die durch Benutzereingaben gefährdet sind, existieren solche Maskierungsfunktionen.






