Sonntag, 5. Februar 2012 |
Um SQL-Injection zu verhindern, muss man sich nur an den alten Grundsatz "Traue nie dem Client" halten: Alle Benutzereingaben müssen geprüft und gefiltert werden. Welche Möglichkeiten es dafür gibt und wie ein Angreifer die Filter austricksen kann, erfahren Sie in dieser Folge.
Der einfachste Fall sind Parameter, die nur Zahlen enthalten dürfen. Die Eingaben können dann einfach in Werte aus dem passenden Bereich, z.B. Integer, umgewandelt werden, und eventuell eingeschleuster Schadcode wird eliminiert. Je nach Anwendungsfall muss der sich ergebende Zahlenwert noch auf seine Gültigkeit im Rahmen der Anwendung geprüft werden, um keine unerwünschten Fehlermeldungen zu erzeugen.
Auch Parameter, die nur Buchstaben und bestimmte, genau definierte, harmlose Sonderzeichen wie z.B. ein Leerzeichen enthalten dürfen, lassen sich recht einfach prüfen und gegebenenfalls filtern. Über reguläre Ausdrücke kann geprüft werden, ob die Eingabe wirklich nur die gewünschten Zeichen enthält, und alle unerwünschten Zeichen können gelöscht werden.
N E U ! Security aktuell
Täglich aktuelle Security-Infos!
Parameter, die für SQL-Injection verwendbare Sonderzeichen enthalten können, sind schwieriger zu prüfen und zu filtern. Filter, die bestimmte Zeichen löschen oder maskieren, können unter Umständen vom Angreifer ausgetrickst werden. Wie beim Verhindern von Cross-Site-Scripting gilt daher, dass besser eine Positivliste zulässiger Werte verwendet werden sollte. Und ebenso wie für Cross-Site-Scripting gibt es auch für SQL-Injection Cheat-Sheets mit Möglichkeiten, Filter zu umgehen. Die Version von ha.ckers.org enthält zusätzlich eine Kodierfunktion, um ASCII-Text in verschiedene andere Formate umzuwandeln.
Wird das einfache Anführungszeichen ' ausgefiltert, verhindert das keine Angriffe in numerische Parameter (About Security #168): Wird der betreffende Parameter für die SQL-Abfrage nicht in ' eingeschlossen, muss der Angreifer auch keine '-Zeichen schließen.
Wird das Kommentarzeichen -- ausgefiltert, mit dem der Angreifer auf seinen
eingeschleusten Schadcode folgende Teile der SQL-Abfrage auskommentiert,
könnte versucht werden, den eingeschleusten Code so zu formulieren, dass auch
ohne Auskommentieren eine gültige SQL-Anweisung entsteht. Statt
nix' or 1=1--
könnte z.B.
nix' or 'a'='a
verwendet werden (About Security
#166).
Wird eine einfache Blacklist verwendet, um unerwünschte
Schlüsselwörter auszufiltern, reicht oft eine Änderung der
Schreibweise oder Codierung, um den Filter zu umgehen. Wird beispielsweise das
Schlüsselwort SELECT ausgefiltert, kann stattdessen oft
eine Variante wie sElEcT, SELSELECTECT, %53%45%4c%45%43%54
oder %2553%2545%254c%2545%2543%2554 verwendet werden.
Werden Leerzeichen ausgefiltert, können sie durch Kommentare ersetzt werden. Aus dem Beispiel zur Abfrage der Datenbankversion aus About Security #171,
nix' UNION SELECT NULL, @@version, NULL--
wird dann z.B.
nix'/*bla*/UNION/*bla*/SELECT/*bla*/NULL,/*bla*/@@version,/*bla*/NULL--
Der SQL-Interpreter behandelt die Kommentare wie Whitespace-Zeichen. In MySQL können Kommentare sogar innerhalb von Schlüsselwörtern verwendet werden - für einen Angreifer eine ideale Möglichkeit, um manche Filter zu umgehen:
nix' UNI/*bla*/ON SELE/*bla*/CT NULL, @@version,NULL--
wird von MySQL genauso ausgeführt wie die nicht verunstaltete Abfrage.
Werden von der Webanwendung bestimmte Strings ausgefiltert, die für
den SQL-Injection-Angriff benötigt werden, können sie dynamisch
in der Abfrage zusammengesetzt werden. Wird der für das letzte
Beispiel in About Security
#170
benötigte String passwort ausgefiltert, kann er in MySQL
z.B. als concat('pas','swort') geschrieben werden. Aus
entwickler.press' UNION SELECT benutzername, passwort, id FROM benutzer--
wird dann
entwickler.press' UNION SELECT benutzername, concat('pas','swort'), id FROM benutzer--
Meist stellen die Datenbanken mehrere Funktionen zur Manipulation von Strings bereit, die alle verwendet werden können, um einen gefilterten String an der Prüffunktion vorbeizuschleusen.
Erlaubt die Datenbank die dynamische Ausführung von SQL-Anweisungen,
indem eine Funktion mit einem die SQL-Anweisung darstellenden String
aufgerufen wird, können auch darüber Filter umgangen werden. In
MS-SQL wird dafür die Funktion exec() verwendet, z.B.
so:
exec('select * from benutzer')
In MS-SQL können Strings über + miteinander verbunden werden.
Eine Blacklist, die Schlüsselwörter wie SELECT oder
unerwünschte Strings wie den Tabellennamen benutzer
enthält, könnte also durch Eingabe von
exec('se'+'lect * from ben'+'utzer')umgangen werden.
In der nächsten Folge erfahren Sie, wieso das oft zur Verhinderung von SQL-Injection-Angriffe verwendete Escapen von Sonderzeichen wie dem ' nicht zwingend zum Erfolg führt.
Wenn Sie Fragen oder Themenvorschläge haben, können Sie diese gerne an die angegebene E-Mail-Adresse senden oder im Security-Forum einbringen!