Beim Arbeiten mit Datenbanken muss man sich gegen verschiedene Angriffsmöglichkeiten wappnen. Zu den verbreitetsten zählen SQL-Injections (dt. SQL-Einschleusungen). Hierbei versucht der Angreifer SQL-Befehle als Parameter, die in die MySQL-Abfrage einfließen, zu übergeben.
Um sich gegen Angriffe zu wehren, muss man die Methode verstehen. In diesem Beispiel geht es darum, dass völlig andere Befehle an das Ende eines über die GET-Methode übergebenen Parameters gehängt wird.
<?php $user_id = $_GET['id']; $abfrage = "SELECT namen FROM user WHERE id = ".$user_id; $ergebnis = mysql_query($abfrage); // ... ?>
Nehmen wir an, der User hat die id = 3. Die URL für diesen Code wäre dann vermutlich dateiname.php?id=3. Ein bösartiger Angreifer kann nun, da der Inhalt der Variable $_GET['id'] nicht auf seine Plausiblität geprüft wird, schadhaften Code anhängen:
dateiname.php?id=3';+DELETE+FROM+user+WHERE+id+>+'0';--
Der SQL-Befehl, der ausgeführt wird, sieht also so aus:
SELECT namen FROM user WHERE id = '3'; DELETE FROM user WHERE id > '0'--'
In diesem Fall würden zusätzlich zum Auslesen des Namens des User mit der id=3 alle Datensätze, deren id größer als 0 ist, in der „user“-Tabelle gelöscht. Die beiden - - am Ende sind Kommentare in der SQL Sprache, vergleichbar mit doppelten Schrägstrichen in PHP oder C. Es werden alle nachfolgenden Zeichen, in diesem Fall der Rest der ursprünglichen Abfrage, also ein ' ignoriert.
Bei Integer-Variablen, also Variablen, die nur Zahlen enthalten sollten, wie in dem oberen Beispiel, ist die Abwehr recht einfach: Man muss die übergebene Variable in einen Integer-Wert umwandeln:
<?php $user_id = (int) $_GET['id']; $abfrage = "SELECT namen FROM user WHERE id = ".$user_id; $ergebnis = mysql_query($abfrage); // ... ?>
Der Variable $user_id wird nun in jedem Fall der Integer-Wert des Variable $_GET['id'] zugewiesen. Das Anhängen eines funktionierenden SQL-Befehls an den Parameter wird somit unmöglich.
Bei String-Variablen stellt PHP eine bequeme Funktion zu Verfügung, die alle SQL-Befehle erkennt und unschädlich macht bzw. maskiert: mysql_real_escape_string('string').
<?php $user_name = mysql_real_escape_string($_POST['name']); $abfrage = "SELECT id FROM user WHERE name = '".$user_name."'"; $ergebnis = mysql_query($abfrage); // ... ?>
Sind nur GET-Variablen von dem unerwünschtem Verändern von Daten betroffen? Auf den ersten Blick kann es so aussehen, da man bei GET-Variablen nur die Adresszeile des Browsers verändern muss, doch auch POST-Variablen kann man mit den entsprechenden Tools (z.B. dem Firefox Addon Tamper Data) verändern. Auch Cookies sind vom User veränderbar.
In diesem Sinne:
ALL INCOMING DATA IS EVIL