Okt 10

Aus der neuen Serie auf Entwicklerblog.at.tf: Sicherheit für Webseiten

Was sind SQL-Injections?

Als SQL-Injection versteht man die Aussnutzung von schlecht programmierten SQL-Abfragen, vor allem bei Authentifizierung von Besuchern.
Dabei wird das Problem ausgenutzt, dass viele Webprogrammierer die Nutzereingaben ungefiltert direkt in die SQL-Abfragen übernehmen.

Wie funktioniert so einen SQL-Injection?
Hier ein kleines Beispiel in PHP, wie man eine User-Authentifizierung besser nicht bauen sollte:
1: $username = $_POST['username‘];
2: $password = $_POST['password'];
3: $sql = “SELECT * FROM tbl_user WHERE username=’”. $username .”‘ AND password=’”. $password.”‘”;
4: …

Schaut ja eigentlich auf den 1. Blick recht harmlos aus: Die SQL- Abfrage soll mir all jene User zurückliefern, bei denen entsprechender Username und das Passwort übereinstimmen.

Wenn ich z.B. als Usernamen Karl übergebe und als Passwort Myverlongpassword würde die SQL folgendermaßen an den Server geschickt
werden:
SELECT * FROM tbl_user WHERE username=’Karl’ AND password=’Myverlongpassword’

Nun kommt aber der Clou an der ganzen Sache:
Wie wäre es, wenn wir als Usernamen Admin übergeben und als Passwort x’ OR 1=1′?
Die SQL-Abfrage würde wie folgt lauten:
SELECT * FROM tbl_user WHERE username=’Admin’ AND password=’x’ OR 1=1

Hoppla, wenn es tatsächlich einen User mit dem Namen Admin gibt (solch einen Benutzernamen sollte man für Admins sowieso nicht verwenden) wird noch überprüft, ob das Passwort ‘x’ ist oder ob die Zahl 1 gleich der Zahl 1 ist, was wohl immer und überall zutreffen sollte. Wurde ein Account ‘Admin’
gefunden, wird der User nun eingeloggt, usw.

Wie schütze ich mich vor SQL-Injections?
Ein Grundregel für dich sollte beim Programmieren immer lauten: In ein Programm oder Script darf nie etwas ungefiltert von Außen hereinkommen. Das können Abfragen von anderen Webdiensten, Schnittstellen, etc. sein oder wie in unserem Fall eben Texteingaben z.B. aus einem Formularfeld.

Um Eingaben zu filtern gibt es sehr viele verschiedene Möglichkeiten und Ansätze:
Eine sehr effektive Möglichkeit wäre, nur bestimmte Zeichen wie z.B. a- z, A-Z, 0-9 durchzulassen. Hierfür gibt es bereits zahlreiche fertige Scripte, wie z.B. folgendes PHP-Script:

$string = preg_replace ( ‘/[^a-z0-9 ]/i’, ”, $string );
Jedoch sollte man eventuell einige Sonderzeichen für Passwörter erlauben, da diese das Knacken z.B. durch BruteForce (durchprobieren aller Kombinationen) erheblich erschweren oder zumindest verlängern.

Eine weitere wichtige Funktion stammt direkt von MySQL:
mysql_escape_string()

Diese “escaped” zahlreiche gefährliche Zeichen wie in unserem Beispiel das Apostroph (‘) mit Hilfe von Backslashes (\). In unserem Beispiel oben würde aus x’ OR 1=1 dann gleich x\’ OR 1=1 werden, was in der SQL-Abfrage keine Probleme bereiten würde.

Einen Kommentar schreiben