echo $begrüßung;
Wenn ich Variablen mittels eine URL übergebe muß ich wie folgt schreiben:
In einer URL stehen keine Variablen. PHP war früher so frei und hat den Querystring interpretiert und daraus direkt Variablen angelegt. Zusammen mit schlampiger Programmierung war und ist das eine Sicherheitslücke. Wenn man davon ausgeht, dass PHP eine Variable beim ersten Zugriff anlegt, und sich nicht um eine explizite Initialisierung kümmert, kann durch diesen register_globals genannten Mechanismus die Variable nun alles mögliche unvorhergesehene enthalten.
for ($i = 0; $i < 10; $i++)
$s = $s . $i; // alternative Schreibweise: $s .= $i;
In dieser Schleife werden die Zahlen einfach an $s angehängt. Beim ersten Durchlauf existiert $s noch nicht. Der Lesezugriff ergibt den Wert null, der durch PHPs automatische Typumwandlung in einen Leerstring umgewandelt wird. Mit eingeschaltetem register_globals könnte man
http://example.com/script.php?s=irgendwas
aufrufen und hätte $s damit vorbelegt. Deshalb sollen Variablen vor dem ersten Zugriff immer mit einem definierten Wert versehen werden.
$s = '';
for ($i = 0; $i < 10; $i++)
$s = $s . $i;
register_globals ist mittlerweile (PHP5) nicht mehr standardmäßig eingeschaltet. Trotzdem ist eine explizite Variableninitialisierung vorzuziehen. Vielleicht schaltet das irgendein Depp ja wieder ein, weil das tolle Hastenichgesehen-Script von Kennstenich sonst nicht läuft.
naechste_seite.php?a=1&b=2
$a=$_GET['a'];
$b=$_GET['b'];
PHP stellt die Werte aus dem Querystring und die Werte aus POST-Formularen in den Arrays $_GET und $_POST zur Verfügung. Das sind ganz normale Arrays, deren Elemente sich in nichts von anderen Variablen unterscheiden. Der Unterschied zu selbst erzeugten Arrays ist, dass $_GET und $_POST superglobal sind, und damit auch innerhalb von Funktionen bekannt sind, doch der ist in dem Zusammenhang nicht weiter relevant.
Da es früher, als register_globals noch eingeschaltet war, (leider) üblich war, auf die Variablen direkt zuzugreifen, und sie überall kreuz und quer im Script verteilt waren, hatte man mit dem Ausschalten nun das Problem, dass die Variablen nun plötzlich leer waren. Die einfachste Lösung sah so aus, wie du sie notiert hast. Es hieß dann, man müsse die "Werte erst abholen". Und so verbreitete sich diese Unsitte des $foo = $_GET['foo']; Das hat auch noch den Nachteil, dass an $foo nicht mehr direkt zu sehen ist, dass dessen Wert eine Benutzereingabe ist, mithin auch ungeprüftes Zeug enthalten kann. Einem $_GET['foo'] sieht man sofort seine Herkunft an.
PHP gibt Hinweismeldungen beim Zugriff auf nicht vorhandene Variablen aus, die aber standardmäßig unterdrückt werden. Damit lassen sich nicht nur uninitialisierte Variablen finden sondern auch Tippfehler. Wenn man das error_reporting auf E_ALL stellt, kann man diese Hinweise sehen. Diese Einstellung sollte man immer beim Entwickeln gesetzt haben.
echo $a<br>;
bzw. echo $_GET['a'], '<br>';
Abgesehen vom Syntax-Fehler, solltest du unbedingt folgenden Lehrsatz verinnerlichen: Wenn Werte in einem bestimmten Kontext ausgegeben werden, müssen diese zwingend dem Kontext entsprechend behandelt werden.
Du übergibst hier einen Wert in den Kontext HTML. HTML ist ein Gemisch aus Anweisungen und Daten. Für die Daten gibt es Regeln, damit diese nicht als Anweisung missinterpretiert werden können. Diese besagen, dass die HTML-eigenen Zeichen besonders zu notieren sind. PHP hilft hier mit der Funktion htmlspecialchars(). Ausgaben in Richtung HTML sollten stets mit dieser Funktion behandelt werden:
echo htmlspecialchars($_GET['a']), '<br>';
Das <br> bleibt davon ausgenommen, denn das ist ja eine Anweisung und kein Wert.
Kleines Beispiel gefällig?
http://example.com/script.php?name=<b>fett</b>
im Script:
echo 'Dein Name ist: ', $_GET['name'];
Und nun stell dir statt <b> ein <script> vor ...
Probier nun das htmlspecialchars() aus.
Dein Name ist: <b>fett</b>
Das sieht dann zwar immer noch doof aus, aber die unsinnige Eingabe wurde wenigstens nicht vom Browser ungewollt als Anweisung interpretiert.
Wenn ich Variablen aus einer Datenbank abfrage erhalte dann wie folgt:
Auch in einer Datenbank stehen keine Variablen drin, sondern einfach nur Daten bzw. Werte. Es gibt einige Funktionen, die diese Daten zurückliefern. Deren Ergebnis kann man in Variablen ablegen, muss man aber nicht zwingend.
$sql="select a, b from tabelle where irgendwas='irgendwas'";
Auch hier hast du wieder einen Kontext, in dem Anweisungen mit Daten gemischt übertragen werden. Deshalb gilt auch hier wieder obiger Lehrsatz. Allerdings ist hier der Kontext nicht HTML sondern MySQL-Statement. Und dafür stellt PHP die Funktion mysql_real_escape_string() zur Verfügung.
$sql = sprintf("SELECT a, b FROM tabelle WHERE a = '%s' AND b = '%s'",
mysql_real_escape_string($_GET['a']),
mysql_real_escape_string($_GET['b']));
So sieht das ganze auch noch etwas übersichtlicher aus, als wenn man die Funktion mysql_real_escape_string() mittels Stringverkettung einbettet.
Zum Rest sag ich nichts weiter, dafür findest du nicht nur ein Beispiel im PHP-Handbuch.
Erwähnt sei noch ein PHP-Feature namens Magic Quotes, das sich auf die Fahne geschrieben hat, gegen SQL-Injection zu sein. Jedoch arbeitet es die Maskierungen bereits in die Eingabedaten ein, ohne darauf Rücksicht zu nehmen, in welchen konkreten Ausgabekanal diese Daten mal später fließen werden, und ob der vielleicht eine ganz andere Bearbeitung benötigt. Wie man die Magic Quotes loswird, steht im velinkten Artikel.
In wie weit kann ich aber darüber "bösen Code" vermeiden?
Wichtig ist, obigen Lehrsatz konsequent anzuwenden.
Was muß ich da noch zusätzlich beachten, bzw. wie sollte ich die übergebenen Variablen prüfen.
Je nach deinen Anforderungen kannst du noch zusätzlich diverse Prüfungen einbauen. Beispielsweise Variableninhalte auf bestimmte Eigenschaften hin testen. Enthalten sie das, was du erwartest? Enthalten sie Dinge, die unbedingt ausgeschlossen werden müssen? Z.B. kommen in einer E-Mail-Adresse keine Zeilenumbruchszeichen vor. Wenn die doch dort zu finden sind, dann kann das nichts gutes bedeuten.
Insgesamt ist das ein komplexes Thema, das man nicht in ein paar Sätzen abhandeln kann. Du musst dir immer überlegen: Was für Daten will ich haben? Welche will ich nicht haben? Wenn ich ein Angreifer wäre, wie könnte ich mein System ungewollt ausnutzen? Was habe ich dagegen getan? Dazu gehört auch, dass man sein eigenes Script mit unsinnigen Werten aufruft, um so zu testen, dass es dagegen immun ist. Welche Zeichen haben im jeweiligen Kontext eine Sonderbedeutung, und wie reagiert mein Script, wenn diese als normale Daten daherkommen?
echo "$verabschiedung $name";