Содержание статьи
warning
Подключаться к машинам с HTB рекомендуется только через VPN. Не делай этого с компьютеров, где есть важные для тебя данные, так как ты окажешься в общей сети с другими участниками.
Разведка
Сканирование портов
Адрес машины — 10.10.10.225, добавляем его в /
как sink.
.
Справка: сканирование портов
Сканирование портов — стандартный первый шаг при любой атаке. Он позволяет атакующему узнать, какие службы на хосте принимают соединение. На основе этой информации выбирается следующий шаг к получению точки входа.
Наиболее известный инструмент для сканирования — это 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
Он действует в два этапа. На первом производится обычное быстрое сканирование, на втором — более тщательное сканирование, с использованием имеющихся скриптов (опция -A
).

В результате сканирования находим три открытых порта: 22 (служба SSH), 3000 (Gitea) и 5000 (Gunicorn). Начнем с Git.

Мы видим какие‑то имена пользователей (запишем их, могут пригодиться!), но больше ничего интересного нет. Поэтому переходим к Gunicorn. На сайте, который он отдает, нужно регистрироваться. Сделаем это, авторизуемся и посмотрим, что нам станет доступно.
Осмотр сайтов я рекомендую проводить через Burp, чтобы можно было просмотреть все отправляемые и получаемые данные. Так после отправки комментария в ответе замечаем заголовок Via
. Это заголовок для прокси, в котором указано haproxy
.


HAProxy — это серверное приложение, которое обеспечивает высокую доступность сайта и балансирует нагрузку TCP и HTTP-приложений между несколькими серверами.
Дальше я попытался посканировать директории. У меня ничего не вышло, зато сообщение об ошибке помогло выяснить используемую версию HAProxy — 1.9.10.

Погуглив, узнаем, что эта версия уязвима к атаке HTTP Request Smuggling.
Точка входа
HTTP Request Smuggling
HTTP Request Smuggling — это метод вмешательства в процесс обработки сайтом HTTP-запросов, полученных от одного или нескольких пользователей. Уязвимость часто имеет критический характер и позволяет злоумышленнику обойти меры безопасности, получить несанкционированный доступ к конфиденциальным данным и напрямую поставить под угрозу других пользователей приложения. Уязвимость возникает из‑за того, что спецификация HTTP предоставляет два разных способа указать, где заканчивается запрос: заголовок Content-Length
и заголовок Transfer-Encoding
.
Заголовок Content-Length
прост: он определяет длину тела сообщения в байтах. Например:
POST / HTTP/1.1Content-Type: application/x-www-form-urlencodedContent-Length: 6p=test
Заголовок Transfer-Encoding
может применяться для указания того, что используется тело сообщения с фрагментированным кодированием. Это значит, что тело сообщения содержит один или несколько блоков данных. Блоки устроены так. Сначала идет размер блока в байтах (в hex), затем знак новой строки, а дальше — содержимое блока. Сообщение заканчивается блоком нулевого размера. Например:
POST / HTTP/1.1Content-Type: application/x-www-form-urlencodedTransfer-Encoding: chunkeda
param=test
0
Так мы можем использовать одновременно два заголовка. Первый сервер будет разделять запросы по первому заголовку, а второй — по второму, тем самым встраивая свои запросы и пропуская их дальше.
Приступим к реализации. Отправим комментарий и перехватим запрос в Burp Proxy.

Его стоит преобразовать следующим образом: укажем заголовок Transfer-Encodeing:[\
и поменяем значение Connection
на keep-alive
. После чего дублируем заголовки запроса в тело запроса.

После редиректа видим явно не тот комментарий, который отправляли.


Дело в том, что внутренний сервер неправильно интерпретировал размер переданных данных из‑за путаницы в определяющих его HTTP заголовках, поэтому отобразил больше информации, чем должен был. Блок дополнительной информации, отображенной в комментарии, был взят из следующего запроса другого пользователя. В этом запросе передавались cookie
другого пользователя, которые мы сразу подставляем себе и перезагружаем страницу. Как можно заметить, в данный момент мы имеем сессию администратора сайта.

Так как это сервис хранения заметок, сразу просмотрим, что может хранить админ. Находим три заметки.

Каждая из них содержит учетные данные.

Точка опоры
С найденными учетными данными получается авторизоваться в Git от имени root
. Находим очень много коммитов, которые стоит просмотреть. Оттуда мы можем получить еще какие‑нибудь учетные данные, секреты, токены или просто узнать используемые технологии.

Я начал просмотр с конца. Важные данные нашлись в коммите вот по этой ссылке:
http://sink.htb:3000/root/Log_Management/commit/e8d68917f2570f3695030d0ded25dc95738fb1baa

А в этом коммите нашелся приватный ключ:
http://sink.htb:3000/root/Key_Management/commit/b01a6b7ed372d154ed0bc43a342a5e1203d07b1e

Необходимо проверить этот ключ. Для этого сформируем список пользователей и попытаемся подключиться по SSH. Для автоматизации я использовал Metasploit Framework.
msfconsole
use auxiliary/scanner/ssh/ssh_login_pub
set RHOSTS sink.htb
set USER_FILE users.txt
set KEY_PATH root.key
run


В итоге находим пользователя, к учетке которого подходит ключ. Так мы получаем стабильную точку опоры в виде доступа по SSH.

Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»