SQL Injection ist nach wie vor eine der Hauptmethoden, wenn es um Datendiebstahl geht. Was ist SQL Injection und wie schützt man als Entwickler seinen Code davor?
Rechtlicher Hinweis:
Bevor sich jemand durch den Artikel angespornt fühlt, das Wissen an fremden Webseiten auszuprobieren, sollte sich bewusst sein, das dies (straf)rechtliche Konsequenzen nach sich führen kann.
Was ist SQL Injection?
Der Angreifer versucht bei SQL Injection, die Datenbankabfrage einer (Web) Anwendung um eigene Datenbankbefehle zu erweitern. So ist es das Ziel des Hackers, die volle Kontrolle über die Datenbank zu erlangen, um Daten auszulesen, zu manipulieren oder schlicht zu löschen.
Ein Beispiel für SQL Injection anfälligen Code:
§result = mysql_query("SELECT * FROM users WHERE username = '". $_GET['username'] ."'");
Die Sicherheitslücke entsteht dadurch, das die Benutzer Eingaben ungeprüft und unmaskiert direkt an die Datenbank weitergeleitet werden. Solange die Benutzer normale Eingaben machen, ist das kein Problem. Was passiert aber wenn z.B. "'; UPDATE users SET type='admin' WHERE username='ich';" eingegeben wird?
Dann würde folgendes Query an die Datenbank geschickt werden:
"SELECT * FROM users WHERE username = ''; UPDATE users SET type='admin' WHERE username='ich';"
Dem Query aus der Anwendung wurde ein zweiter Datenbankbefehl untergeschoben, um einen Benutzer zum Admin zu erheben.
Schutz vor SQL Injection
Die eingegebenen Daten müssen entsprechend maskiert (escaped) werden. Das heisst alle Datenbank spezifischen Sonderzeichen müssen passend umgeschrieben werden. Für diese Aufgabe gibt es bereits einige Datenbank spezifischen Funktionen wie etwa
mysql_real_escape_string.
Beispiel für die Verwendung von mysql_real_escape_string()
§result = mysql_query("SELECT * FROM users WHERE username = ".
"'". mysql_real_escape_string($_GET['username']) ."'");
Noch besser ist die Verwendung von
prepared Statements und der
PDO Klasse. Das Query wird kompiliert und dabei werden Platzhalter für die Daten im Query gebunden. Das heisst, die Benutzerdaten werden nicht mehr als möglicher SQL Befehl interpretiert, sondern nur noch korrekt an den entsprechenden Spalte eingefügt. Ausserdem lässt sich je nach Datenbank unter Umständen eine Performance Steigerung erzielen, insbesondere wenn das selbe Query mit unterschiedlichen Daten ausgeführt werden soll.
Beispiel für ein prepared Statement
$sth = $dbh->prepare("SELECT * FROM users WHERE username = ?");
$sth->execute(array($_GET['username']));
$result = $sth->fetch(); // oder $sth->fetchAll();
Hinweis
Die notwendigen, zusätzlichen Eingabe Überprüfungen sind im Beispiel der Übersichtlichkeit geopfert.]
Zur Artikel Übersicht
PHP Sicherheit
Kommentar Verfassen