Финальный апдейт по стажировке Positive Technologies

Со времён предыдущего апдейта прошли следующие вебинары:

  • SSRF и HTTP Response Splitting;
  • Основы Reverse Engineering;
  • Computer Forensics, хотя я бы назвал его Incident Response;
  • OSINT и социальная инженерия.

Все эти вебинары объединяет то, что они очень интересные и к ним не прилагалось никакого практического задания, так что не будем заострять на них внимание. Главная тема — итоговый квест, который завершил всю стажировку.

Входные данные: IP-адрес сайта вымышленной мебельной компании. Сайт базируется на Bitrix CMS и на нём тут и там расположены кастомные ресурсы, либо выдающие флаги, либо ведущие на серверы с заданиями, выдающими флаги.

pt-finale-root

Теперь о флагах по порядку. Для флагов, которые мне удалось раздобыть ещё в процессе выполнения квеста, я распишу решение насколько это возможно подробно. Для тех, с которыми я не справился — в общих словах.

Флаг 1.

На сайте имеется страница «Контакты», на которой расположена подозрительная форма загрузки.

pt-finale-task1

Естественно, тут же смотрим исходники страницы.

Видим сразу две формы загрузки, одна из которых закомментирована. Закомментированная форма ведёт на сервер с последним октетом адреса 202, а существующая на сервер с последним октетом — 217. Первый флаг расположен на 217-м.

Увы, мне так и не удалось найти точку входа. Кнопка «Upload» на странице отправляла multipart на 217-й сервер, на пустую страницу index.php, которая отвечала 200 OK на что угодно и не сообщала ни о каких ошибках. Я пробовал слепые XXE, пытался заставить 217-й сервер обратиться к своему серверу за DTD, но это не работало. Позже я заметил параметр debug=1, который должен был включить вывод и сделать сервер более разговорчивым, но я, почему-то, решил, что параметр нужно отправлять на страницу index.php на 217-м сервере, тогда как его нужно было отправить на саму страницу «Контакты», где форма и содержалась. Отправка POST вместо GET с параметром debug=1 переключала вывод и сервер начинал ругаться на ошибку парсинга docx. Решение задания заключалось во внедрении XXE-пейлода в docx-документ и скармливании этого всего серверу. Очень интересное задание, жаль, что не удалось к нему даже подступиться.

Флаг 2.

Пожалуй, интереснейший флаг из всех, что были в квесте. Упомянутая выше закомментированная форма ведёт на 202-й сервер. Индексовая страница поинформативнее, нежели на 217-м.

pt-finale-task2-1

Перебираем директории, видим каталог /.git, восстанавливаем его содержимое, страницу index.php, смотрим.

Если передать параметр ?format=xml, код переключится в режим парсинга XML-документа, а тег должен быть xek. Выглядит несложно. Пейлод не отличается от тех, что были в домашней работе по XXE. Отсюда при помощи враппера php://filter можно читать файлы, не боясь, что их содержимое сломает парсинг, но где же флаг? Сканируем сервер nmap’ом, видим порт 666, обращение по адресу X.X.X.202:666 возвращает ошибку 403, потому что сервер отвечает только локалхосту. Идём изнутри, обращаемся туда же при помощи XXE, в ответе страница с формой, делающей GET с параметром ?limit=1. 

pt-finale-task2-0

Делаем этот запрос вручную, получаем ответ: good job, but not so good. Параметр limit явно сигнализирует о возможности sql-инъекции, но очевидные варианты не проходят. Можно пойти с обратной стороны. Читаем конфиг апача: /etc/apache2/sites-enabled/000-default.conf. Отсюда узнаём, что сайт на порту 666 хостится в каталоге /var/www/sqli/, идём туда, читаем index.php. Теперь мы располагаем всеми данными о том, как происходит фильтрация и сам запрос.

Фильтруются далеко не все пробельные символы, берём %a0, строим инъекцию: 1%a0into%a0outfilE%a0‘/tmp/flag’. База пишет флаг в указанное место, читаем, декодируем base64, флаг наш.

Флаг 3.

Перебирая файлы в директориях, можно было заметить, что в каталоге /old/ имеются файлы с расширением php5, в ответ на обращение к которым возвращается заголовок X-Powered-By: PHP-CGI. Уязвимость CVE-2012-1823, некогда прошумевшая, позволяет при помощи обращения X.X.X.147/old/index.php5?-s прочитать исходники файла. Обращаемся таким образом к файлу и получаем флаг.

Флаг 4.

На сайте имеются каталоги продукции и услуг, которые выглядят как /products/1/ и /services/1/. Флаг находился по адресу /services/0/index.php и отдавался в заголовке ответа X-Flag.

Флаг 5.

Корневая страница сайта устанавливает странные куки:

admin=0; user=ee11cbb19052e40b07aac0ca060c23ee; super=0;

А страница /admin.php не даёт смотреть содержимое, возвращая текст «Prohibited». Гуглим куку user, оказывается, что это слово user в md5. Аналогичным образом, устанавливаем в куку admin слово admin, захэшированное в md5. Смотрим страницу admin.php — никаких изменеий, устанавливаем две куки:

admin=21232f297a57a5a743894a0e4a801fc3; super=1;

Вот теперь страница признаёт нас за админа и отдаёт положенный флаг.

Флаг 6.

Этот флаг был всё в том же каталоге /old/ на странице admin.php5. Страницу я в ходе квеста не нашёл, потому к заданию не приступал. Выглядит как страница с полями для ввода капчи, логина и пароля.

pt-finale-task6

Приложу исходники.

Похоже, задание было на внимательность при просмотре ответа сервера, ведь страница выдаёт правильность угаданного логина комментарием. Оставалось перебрать пароль.

Флаг 7.

На стартовом сервере в sitemap.xml упоминалась страница /old/include.php5?type=file. При обращении к ней происходил редирект на другой сервер, к странице include.php. Подставив параметр ?type=file получаем вывод из трёх слов:

TEST LOG TMP

Помимо этого, на сервере была также страница phpinfo.php. Оказалось, задачка была на LFI через phpinfo(), я о таком до этого не знал. Пробовал подбирать значение второго параметра, при помощи фаззинга определил, что это file, но пейлоды в духе file=../../../etc/flag не отрабатывали. После нахождения третьего флага через ?-s я решил, что нужно прочитать исходники якобы старой версии страницы — include.php5 на стартовом сервере и через них понять, чего хочет include.php. Попытка запросить /include.php5?-s приводила к срабатыванию защиты, которая ругалась на применение короткой черты.

pt-finale-task7

Решив, что этот таск на обход защиты, до истечения времени я искал способы обмануть типа-WAF. Исходники задания:

Флаг 8.

На стартовом сервере обращение к каталогу /backup перенаправляло на другой сервер, на страницу index.php со следующим выводом:

pt-finale-task8-0

Ещё в первый день вручную подобрал несложную комбинацию, которая заставляла сервер перестать ругаться:

?server=127.0.0.1&db=mysql&user=root&password=root

Однако тогда наличие параметра с IP не заставило особо задуматься, хотя я и подставлял туда адрес своего сервера и смотрел логи (ну порт 3306 же, о чём я вообще думал?). Позже Burp Suite скажет мне, что при подстановке внешнего IP сервер резолвит его и до меня, наконец, дойдёт.

pt-finale-task8-1

Когда-то я читал в одном из райтапов о CTF об инструменте Rogue MySQL Server. Заряжаю на Vscale свежий сервер, разворачиваю там Rogue, заставляю сервер с заданием присоединиться к своему IP. В логах отсвечивается флаг. Исходник:

Итоги.

Пост итак получился довольно объёмным, так что свои впечатления и мысли о стажировке я опишу в отдельном посте.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *