SQL-Injection: Gefahr für Ihren Server

Bei einer SQL-Injection wird in Parametern versteckter SQL-Code eingeschleust. Damit kann ein Angreifer Daten manipulieren, sich Zutritt erschleichen oder Ihre Datenbank löschen.

Ein Beispiel: Ihr Programm verfügt über ein Anmeldeformular mit Kennworteingabe. Im PHP-Code zum Auswerten der Formulareingaben steht:

$name = $_POST[‘name’ ];

$pw = $_POST[‘pw’];

$sql = “SELECT * FROM user WHERE name=’$name’ ”

Die danach folgenden Zeilen führen die Abfrage durch und vergleichen, ob das Kennwort stimmt. Was aber, wenn ein Benutzer ins Namensfeld schreibt:

xy’;drop database();#

Dann werden tatsächlich drei SQL-Befehle an den Server geschickt:

SELECT * FROM user WHERE name=’xy’;

drop database();

#’

Der Login wird zwar nicht funktionieren, der Angreifer kommt aber mit dem zweiten Befehl zum Erfolg: Ihre Datenbank wird gelöscht – sofern der MySQL-User, unter dem das Skript läuft, die Rechte dazu besitzt.

Die letzte Zeile wird mit dem Kommentarzeichen # eingeleitet. Das verhindert, dass der Rest des ursprünglichen SQL-Befehls einen Syntaxfehler erzeugt.

Abwehr von SQL-Injection

Das wichtigste Abwehrmittel ist das “Escapen”: Alle Zeichen, die vom SQL-Server für eine Zeichenketten-Trennung Verwendung finden können, werden mit einem vorangestellten Backslash aufbereitet. So bewirken sie keine Trennung mehr, sondern gehen als normale Zeichen im String an den Server.

Eine Möglichkeit dazu ist die explizite Umwandlung aller an MySQL übergebenen Strings per mysql_real_escape_string(). Das ist generell sinnvoll, denn in manchen Namen und Bezeichnungen kommen Anführungszeichen vor, die zu SQL-Fehlern führen, weil Zeichenketten nicht richtig abgeschlossen werden. Wird etwa der vierte Musketier per SQL-String gesucht

$name=”D’Artagnan”;

$sql = “select * from user where name=’$name'”;

führt das zu einem Fehler. Wandeln Sie dagegen $name mittels mysql_real_escape_string() vor der Erzeugung des Befehls um, wird effektiv das folgende Kommando an den Server geschickt und dabei das Hochkomma korrekt zum Teil des Namens gemacht:

select * from user where name=’D’Artagnan’

Damit die Umwandlung sensibler Zeichen nicht immer explizit von Ihnen durchgeführt werden muss, gibt es die PHP-Einstellung magic_quotes_gpc. Von der Verwendung dieser Option kann man aber nur abraten. Denn die dabei stattfindende Umwandlung passiert bei jeder Übergabe von Formulardaten. Diese Einstellung bei einem bestehenden System zu ändern, bringt oft Teile der Anwendung aus dem Tritt. Besser ist es, Sie behalten selbst die volle Kontrolle über alle Umwandlungen und setzten bei der Verarbeitung von Eingabedaten gezielt die Funktion mysql_real_escape_string() ein.

Weitere Maßnahmen gegen SQL-Injection

– Bei Fehlern keine SQL-Befehle als Debughilfe ausgeben. SQL-Fehlermeldungen auch nicht in HTML-Kommentaren verstecken.

– Datenbank-User mit minimalen Rechten ausstatten. Login-Überprüfungsskripts mit einem Datenbank-User laufen lassen, der nur Leserechte auf die User-Tabelle hat.

– Open Source-Anwendungen aktualisieren. OS-Entwickler reagieren meist schnell auf Schwachstellen. Umgekehrt droht aber mehr Gefahr durch bekannte Sicherheitslücken.

– Verlassen Sie sich nicht auf die impliziten Typumwandlungen von PHP. Prüfen Sie mit Funktionen wie is_numeric(), ob eine Eingabe dem erwarteten Datentyp entspricht. So ist sichergestellt, dass nicht jemand Textdaten über ein numerisches Feld einschleust. Bei Texteingaben prüfen Sie mit preg_match(), ob die Eingabe einem regulären Ausdruck genügt. So prüfen Sie, ob eine Eingabe nur aus Buchstaben, Zahlen oder dem Unterstrich besteht:

$muster = ‘/^[a-zA-Z09äöüÄÖÜß_]+$/’;

if (!preg_match( $muster, $eingabe))

die(‘Eingabe enthält falschen Zeichen!’);

– Prepared Statements nutzen (ab PHP 5.1). Die verarbeiten Eingaben anders und verhindern damit Injections von vornherein.

Ähnliche Beiträge