mySQL: Schutz vor Angriffen in Datenbankabfragen (SQL Injection)

Normale SQL Abfragen mit direkt eingebundenen Parametern ohne zusätzliche Schutzfunktionen kann sehr böse Folgen haben. Meist merken Sie davon nichts - Ihre Daten sind jedoch in höchster Gefahr. Szenario #1: Ein einfacher Angriff Nehmen wir eine (leider) normale Datenbankabfrage in PHP:

$query = "SELECT * FROM users 
WHERE user='{$_POST['username']}' AND password='{$_POST['password']}'";
Nicht immer müssen die "richtigen" Parameter durch Ihre Oberfläche übergeben werden. Durch einfache Manipulation der Parameter (über gesonderte Abfragen) können beliebige Daten mit POST übergeben werden. Gehen wir von folgenden Parametern aus:
$_POST['username'] = "max";
$_POST['password'] = "' OR ''='";
Dadurch würde das SQL Statement so aussehen:
SELECT * FROM users WHERE user='max' AND password='' OR ''=''
Szenario #2: Auflisten von Benutzernamen & Passwörtern Ebenfalls leicht möglich. Dafür wird eine Datenbankabfrage (SELECT Statement) einfach erweitert:
$query = "SELECT id, name, inserted, size 
FROM products
WHERE size = '$size'
ORDER BY $order LIMIT $limit, $offset;";
Nun wird z.Bsp. der Parameter "size" vom Angreifer modifiziert:
'
union select '1', concat(uname || '-' || passwd) as name, '1971-01-01', '0' from usertable;
--
Dadurch wird folgende SQL Statement an die Datenbank übergeben:
SELECT id, name, inserted, size 
FROM products
WHERE size = ''
union select '1', concat(uname||'-'||passwd) as name, '1971-01-01', '0' from usertable;
--' ORDER BY $order LIMIT $limit, $offset;
Szenario #3: Zurücksetzen / Ändern eines Passwortes Das SQL Statement wird wie folgt zusammengebaut:
$query = "UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';";
Diese kleine Erweiterung des Parameters "uid" reicht aus:
$uid == ' or uid like'%admin%'; --
Dadurch erhält Ihre Datenbank diesen Updatebefehl:
$query = "UPDATE usertable SET pwd='...' WHERE uid='' or uid like '%admin%'; --";
Szenario #4: Zugriff auf das Betriebssystem Ihre Datenbankservers Ihre Abfrage:
$query  = "SELECT * FROM products WHERE id LIKE '%$prod%'";
Wenn jetzt der Parameter "name" entsprechend verändert wird, erhalten Sie folgendes SQL Statement:
SELECT * FROM products
                    WHERE id LIKE '%a%'
                    exec master..xp_cmdshell 'net user test testpass /ADD'--";
Dadurch würde (sofern Sie als entsprechend berechtigter Benutzer verbunden sind) ein neuer Benutzer "test" angelegt werden ... und dieser kann dann natürlich frei auf dem Datenbankserver arbeiten. Schutz Ihrer Daten & Datenbank
  1. Verbinden Sie sich nur als Benutzer mit den benötigten Rechten zur Datenbank. Niemals als Administrator (sa / sysdba / sys / ...)
  2. Prüfen Sie Parameter vor der Benutzung auf Plausibilität. Z.Bsp. bei nummerischen Werten durch die Funktion "is_numeric()".
  3. Escapen Sie jeden anderen Parameter, welchen Sie direkt an die Datenbank weitergeben. Nutzen Sie dafür Funktionen wie "mysql_real_escape_string()", "sqlite_escape_string()", usw.
  4. Geben Sie keine Datenbank internen Informationen heraus (Schema, Views, Spezifikationen, etc.) Diese Infos können leicht für Angriffe genutzt werden und erleichtern die gezielte Manipulation Ihrer Daten.
Beispiel für eine bessere Abfrage:
$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
            mysql_real_escape_string($user),
            mysql_real_escape_string($password));