![]() |
Добьем тему.
Предлагается найти RCE для не очень частой, но довольно тупиковой ситуации, когда есть "голая" LFI, без возможности заливки файлов, без доступа к логам или чему-либо полезному, сессия не стартована. В конце прошлого года известные китайцы (тайванцы) показали, что задача решаема. И не то, чтобы решение было "кривое", нормальное решение, но мы сделаем круче. Сможем обойти более сложную проблему , когда проверяется расширение файла, или даже конкретное имя, или еще и путь до файла. Для минимизации времени на поиски вариантов все скрипты с сайта убраны, оставлен только один (и почищен) - не промахнетесь. В нем строка: Код:
if(isset($_GET['f']) && basename($_GET['f'])==='test.php') include($_GET['f']);Код:
open_basedir /var/www/:/var/lib/php/sessions:/tmpЗадание: 1- Выполнить на таргете phpinfo(). 2- Отдельно будет оцениваться удобство эксплуатации, мы сделаем "конфетку" - надежное 100% срабатывание, без всяких гонок. Срок: две недели. Отлаживаться можно и локально, способы универсальные, работают и в никсах и на винде. Скрипт в аттаче. Флагов нет, присылайте решения в ПМ форума. И сканеры не нужны, не помогут. Никаких секретных каталогов, файлов - нет. Даже картинка тут не при делах. Правила остаются прежними: В теме не флудим, подсказки разрешены только от ТС, ответы присылаем в ПМ. Прошли: =HALK= 1, 2 nix_security 1, 2 Gorbachev 1, 2 joelblack 1 Прохождения |
По поводу тестов на локалке, проверено для php 7.
Судя по манам, должно работать с версии 5.4, но нужно проверять. = upd Для 5.5.20 тоже работает, подтверждаю. |
Не знаю, как здоровый зеленый мужик попадает в клавиатуру, но в решение он попал.
И довольно неплохо. nix_security тоже зарешал, реализацию еще можно допиливать, но уже вполне прилично. Вот даже пришлось выкатить неожиданную полторашку. Почти уверен - он тоже добьет. |
Давайте подумаем, как решать такую задачу.
Раньше мы бы пытались сбрутить темп-файл, который создается при загрузке файла. Ну м.б. по сегфолту положили его не временным а постоянным. Надеюсь никто не будет мучить сервер таска таким поиском. Кстати, один наш общий знакомый недавно подтвердил работоспособность такого решения, возможно он еще отпишется, хотя именно он и заставил меня поискать альтернативное решение. И сегодня мы уже можем зайти с другой стороны. Решение складывается из трех пазлов, по двум уже даны подсказки, одна аж прям почти открытым текстом, вторая пытается быть не такой прямой, а осторожно указывает на блог Orange, который и сам по себе интересен, да еще дает нам новый механизм работы с сессиями, даже когда они не стартованы явно. Полезная вещь, если пропустили ее, рекомендую потестить и разобраться. На рдоте тоже есть подходящий пост. Сложив две технологии мы зарешаем первый пункт таска. Второй пункт - просто сделаем решение технологичным, надежным и удобнымным в эксплуатации. |
Спасибо за таск! Интересный и малоизвестный вектор.
|
Цитата:
Вот мы приходим в ИБ и видим много разных вещей, новых, крутых, невероятных. Учимся пользоваться ими. Но все время остается дистанция, между нами и теми, кто это ресерчил и отлаживал, наполнял содержанием то, что мы называем хакерскими технологиями. Они крутые, а мы только учимся. Но вот сейчас хороший момент, когда можно почувствовать, что мир становится "меньше" и уже не так далеко до тех, кто творит хакерскую историю. А может расстояния остались теми же, а мы выросли. В любом случае мы сейчас делаем то, что пока еще никто в мире не умеет делать. Никто, кроме нас. А мы уже научились выпиливать лобзиком хитрые архивы и сейчас из обычной сессии приготовим еще один такой. С нужным нам содержанием, с нужным именем. И не из-за ошибок в коде скриптов, а в дефолтной системе. Пусть это и не похек интернета, но некоторая новая технология, у которой есть потенциал, а возможно и история с продолжением. Поэтому предлагаю не ждать, когда появятся ответы, а найти их в составе команды первопроходцев. |
Вот за что нравятся задачки дубля, так это за то что там нет воды: вот тебе готовая, популярная проблема, реши ее. И хорошо подвел к ее решению предыдущим заданием. Осталось сложить а+б. Идеально для новичков, самый недооцененный таск.
|
a - https://blog.orange.tw/2018/10/hitco...challenge.html или http://wonderkun.cc/index.html/?p=718, нас интересует принудительное создание сессии с нужной начинкой.
б- поскольку в имени сессии точка недопустима, смотрим /threads/470693/ Ну и, как посоветовал Лайт, соединяем технологии a + б. |
Спасибо за таск, очень понравился, читал ресерч оранжа ранее, было интересно воспроизвести его, да еще и в купе с "штукой" из таска7)
|
Прохождение
Анализ: Поскольку логи недоступны и на сайте нет скриптов аплоада, ищем способы сформировать файл с полезной нагрузкой. Open_basedir разрешает работу в /tmp и в каталоге сессий, а в каталог сайта чмоды писать не дают, да и нечем. Можем инициировать загрузку файла и пытаться сбрутить имя создающегося темп-файла. Но в конце прошлого года был обнаружен более интересный механизм, попробуем поковырять его. Идея: Можно задействовать механизм принудительного создания сессии и проинклюдить ее. Затею нетрудно реализовать в системе с дефолтными настройками, на рдоте тоже была заметка на эту тему, поэтому не экзотика, тестим и разбираемся - чего и как. Для начала смотрим маны и готовим localhost, php v. >=5.4 и для удобства временно установим Код:
session.upload_progress.cleanup = OffОтправляем запрос Код:
curl http://127.0.0.1/index.php -H "Cookie: PHPSESSID=test" -F "PHP_SESSION_UPLOAD_PROGRESS=blahblahblah" -F "file=@/tmp/up.txt"Код:
upload_progress_blahblahblah|a:5:{s:10:"start_time";i:1561714798;s:14:"content_length";i:297312;s:15:"bytes_processed";i:297312;s:4:"done";Т.е. можем вставить произвольный php-код и получаем файл с заданным именем и нужной начинкой Код:
Код:
upload_progress_ZZZ|a:5:{s:10:"start_time";i:1561718417;s:14:"content_length";i:6931748;s:15:"bytes_processed";i:6931748;s:4:Теперь возвращаем session.upload_progress.cleanup = On и двигаемся дальше. Если бы не Код:
if(isset($_GET['f']) && basename($_GET['f'])==='test.php')Тут, к сожалению, известные приемы закончились и дальше придется ресерчить самим. Назвать сессию - 'test.php' мы не можем, точка - недопустимый символ в имени сессии. Поэтому вспоминаем, как в таске #7 мы работали с архивами и помещали в них нужные файлы, как продолжение файловой системы. И basename() будет применен уже не к файлу архива, а к этим файлам, когда мы их запросим. Если контролируемую часть сессии сформировать так, чтобы файл сессии стал валидным архивом, то можно проинклюдить содержимое архива, используя соответствующий враппер. Мысль хорошая, тестим. Phar не подходит по двум причинам - проверяет целостность содержимого и в имени файла обязательно должна быть точка (и хотя бы один символ после нее). Но вот zip нам пригодится. Мы уже умеем добавлять произвольный префикс к нему, да и точка в имени не обязательна. Аналогично можно добавить и суффикс, но этого делать не придется, потому, что есть еще одно замечательное свойство - добавление данных в конец готового архива не ломает его, он их просто игнорирует, не видит. И эти данные становятся частью файла, но не частью архива. Итого имеем неизменяемое начало файла, заголовок сессии (из которого и сформируем архив) и остальную, изменяемую часть сессии. И вот она - магия! Один и тот же файл воспринимается одновременно и как валидный архив с полезной начинкой и как файл сессии, с которым адекватно работает php. Остается решить третью проблему, сессия очищается по окончании загрузки файла и нужно ловить момент, когда полезная начинка существует в файле сессии. Если мониторить размер файла сессии, то происходит примерно следующее, пока работает скрипт загрузки. ---=======----- где: - сессия пуста = файл сессии содержит полезную начинку Можно просто поиграть в гонки, сгенерить много загрузок и много инклюдов, какой-нибудь да сработает. Можно даже один раз запустить загрузку большого файла и множеством запрсов ловить нужное состояние сессии. Мы примерно по этому пути и пойдем, но сделаем процесс более контролируемым и надежным. Реализация Php - однопоточный по своей природе, а нам нужно два потока запускать и контролировать, поэтому лучше использовать чего-нибудь другое. Хотя и тут можно скозлоумничать. На неблокирующих сокетах, или попробовать мультикурл. А давайте попробуем. Оказывается вполне даже работает. Инициируем два соединения, первое аплоадит файл, второе инклюдит сессию через враппер. Код:
curl_setopt($ch1, CURLOPT_URL,$url1);Код:
getshell(),Кстати, в процессе тестов обнаружился такой момент, пустил соединение через прокси Charles и поведение сессии на сервере таска изменилось, файл сессии не очищался еще продолжительное время после окончания работы скрипта загрузки. Так что просто последовательное выполнение запроса загрузки и следом запроса на инклюд - работало на ура. Без всякого шаманства. Не "конфетка", но тоже интересно. |
| Время: 09:30 |