07.092012

SQL Injection verhindern

Eigentlich dachte ich, dass man hierüber heutzutage kein Wort mehr verlieren braucht und sich jeder Softwareentwickler der Gefahr bewusst ist und dementsprechend handelt.

Ich merke aber immer wieder, dass viele Entwickler entweder noch nichts davon gehört haben oder sich der Gefahr einfach nicht bewusst sind.

Daher werde ich hier ein paar grundlegende Dinge zusammenfassen, die jede Software ein Stück sicherer macht.

Die oberste Regel lautet: Prüfe ALLE Usereingaben!

Bei sämtlichen Daten, die man übermittelt bekommt, sollte man grundsätzlich davon ausgehen, dass sie schädlich sind und sie genau überprüfen. Das ist ziemlich einfach, wenn ich genau weiß, wie die Daten in etwa aussehen müssten. Bei einer Postleitzahl weiß ich, dass sie in Deutschland nur Zahlen enthält. Das kann ich folgendermaßen überprüfen:

if(!is_numeric($_GET['plz'])) {
    return false;
}

oder noch besser, da hier gleichzeitig die Länge überprüft wird

if(!preg_match('~^[0-9]{5}$'~, $_GET['plz'])) {
    return false;
}

Das ist ja noch relativ simpel.  Auch einen regulären Ausdruck zur Überprüfung von URLs und Emailadressen bekommt man vielleicht noch hin, auch wenn diese schon deutlich umfangreicher werden.

Aber was macht man, wenn der User einen freien Text in ein Kontaktformular eingeben kann, welches hinterher in einer Datenbank gespeichert werden soll? Hierfür gibt es natürlich ein paar nützliche Libraries, die einem eine Menge Arbeit abnehmen.

Active Data Objects DataBase kurz ADOdb ist eine solche Library, welche eine Menge Datenbanken unterstützt. Hier setzt man die Variablen nicht mehr direkt in das SQL Statement, sondern arbeitet mit Variablen Binding.

Die Query sieht dann nicht mehr so aus:

$db->Execute("INSERT INTO kontaktformular (email, text)
VALUES (".$_GET['email'].",".$_GET['message'].")");

Sondern so:

$db->Execute("INSERT INTO kontaktformular (email,text)
VALUES (?,?)", array($_GET['email'], $_GET['message']));

Das hat nicht nur den Vorteil, dass die Query deutlich leichter zu lesen ist, ADOdb kümmert sich auch darum, dass die Parameter in das SQL Statement eingesetzt werden und sorgt nebenbei noch dafür, dass deren, evtl. schädlicher, Inhalt korrekt escaped wird. Natürlich bietet ADOdb noch eine Menge mehr an nützlichen Funktionen, aber die erkläre ich vielleicht mal in einem anderen Artikel  :-)

Also achtet darauf, je genauer ihr wisst, in welchem Format ihr Daten erhaltet, desto genauer könnt ihr sie auf Gültigkeit prüfen. Das mindeste ist aber, dass man zum escapen von Strings die Funktionen mysql_real_escape_string oder pg_escape_string - je nach Datenbank, benutzt.

 

Zum Schluss noch ein kleiner Tipp, was viele Leute vergessen: Auch Cookiewerte kann ein "böser User" verändern - sie müssen genau so geprüft werden!