Се­год­ня я покажу, как исполь­зовать прош­логод­ний баг в инс­тру­мен­те TeamCity, что­бы соз­дать поль­зовате­ля‑адми­на и таким обра­зом повысить при­виле­гии на хос­те. Затем соз­дадим кон­тей­нер в Portainer, сбе­жим из него бла­года­ря уяз­вимос­ти в runC и смо­жем читать любые фай­лы в сис­теме.

На­ша цель — получе­ние прав супер­поль­зовате­ля на машине Runner с учеб­ной пло­щад­ки Hack The Box. Уро­вень слож­ности задания — сред­ний.

warning

Под­клю­чать­ся к машинам с HTB рекомен­дует­ся толь­ко через VPN. Не делай это­го с компь­юте­ров, где есть важ­ные для тебя дан­ные, так как ты ока­жешь­ся в общей сети с дру­гими учас­тни­ками.

Разведка

До­бав­ляем IP-адрес машины в /etc/hosts:

10.10.11.13 runner.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).

Результат работы скрипта
Ре­зуль­тат работы скрип­та

По резуль­татам ска­ниро­вания име­ем три откры­тых пор­та:

C SSH ничего не поделать, поэто­му перехо­дим к вебу. На пор­те 8000 необ­ходим какой‑то эндпо­инт, так как получа­ем ответ 404, а на пор­те 80 нас встре­чает сайт‑визит­ка.

Ответ сервера 10.10.11.13:8000
От­вет сер­вера 10.10.11.13:8000
Главная страница сайта runner.htb
Глав­ная стра­ница сай­та runner.htb

Точка входа

На сай­те ничего инте­рес­ного най­ти не уда­лось, поэто­му прис­тупим к ска­ниро­ванию.

Справка: сканирование веба c ffuf

Од­но из пер­вых дей­ствий при тес­тирова­нии безопас­ности веб‑при­ложе­ния — это ска­ниро­вание методом перебо­ра катало­гов, что­бы най­ти скры­тую информа­цию и недос­тупные обыч­ным посети­телям фун­кции. Для это­го мож­но исполь­зовать прог­раммы вро­де dirsearch и DIRB.

Я пред­почитаю лег­кий и очень быс­трый ffuf. При запус­ке ука­зыва­ем сле­дующие парамет­ры:

  • -w — сло­варь (я исполь­зую сло­вари из набора SecLists);
  • -t — количес­тво потоков;
  • -u — URL;
  • -H — HTTP-заголо­вок.

Мес­то перебо­ра помеча­ется сло­вом FUZZ.

За­даем все парамет­ры и запус­каем ска­ниро­вание:

ffuf -u http://runner.htb/ -H 'Host: FUZZ.runner.htb' -w subdomains-bitquark-top100000.txt -t 256
Результат сканирования
Ре­зуль­тат ска­ниро­вания

Од­нако ути­лита выводит все вари­анты из сло­варя, поэто­му добавим филь­тр по раз­меру стра­ницы (параметр -fs).

ffuf -u http://runner.htb/ -H 'Host: FUZZ.runner.htb' -w subdomains-bitquark-top100000.txt -t 256 -fs 154
Результат сканирования
Ре­зуль­тат ска­ниро­вания

В ито­ге находим один под­домен, поэто­му обновля­ем запись в фай­ле /etc/hosts:

10.10.11.13 runner.htb teamcity.runner.htb
Главная страница teamcity.runner.htb
Глав­ная стра­ница teamcity.runner.htb

Пе­ред нами TeamCity 2023.05.3. В этой вер­сии есть извес­тная уяз­вимость CVE-2023-42793, которая поз­воля­ет ата­кующе­му обой­ти авто­риза­цию, соз­дав сво­его адми­нис­тра­тора в сер­висе. Исполь­зуем пер­вый най­ден­ный в Google экс­пло­ит и получа­ем логин и пароль добав­ленно­го в сис­тему адми­нис­тра­тора.

python3 exploit.py -u http://teamcity.runner.htb -t token.txt
Эксплуатация уязвимости
Экс­плу­ата­ция уяз­вимос­ти

Те­перь мож­но авто­ризо­вать­ся в TeamCity и осмотреть­ся в сер­висе.

Главная страница сайта
Глав­ная стра­ница сай­та

Точка опоры

Пер­вым делом прос­мотрим зарегис­три­рован­ных поль­зовате­лей и нас­трой­ки бэкапов.

Пользователи TeamCity
Поль­зовате­ли TeamCity
Параметры бэкапа
Па­рамет­ры бэкапа

Те­перь выпол­ним бэкап и ска­чаем архив для ана­лиза локаль­но на сво­ей машине.

Бэкап TeamCity
Бэ­кап TeamCity

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

Содержимое файла users
Со­дер­жимое фай­ла users
Содержимое каталога pluginData
Со­дер­жимое катало­га pluginData

Пос­ле перебо­ра имен поль­зовате­лей TeamCity успешно логиним­ся по SSH с при­ват­ным клю­чом поль­зовате­ля john.

ssh -i id_rsa john@runner.htb
Флаг пользователя
Флаг поль­зовате­ля

Продвижение

Те­перь нам необ­ходимо соб­рать информа­цию. Я буду исполь­зовать для это­го скрип­ты PEASS.

Справка: скрипты PEASS

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

Заг­рузим на хост скрипт для Linux, дадим пра­во на выпол­нение и запус­тим ска­ниро­вание. В выводе мно­го все­го, давай прой­дем­ся по важ­ным момен­там.

Есть нес­коль­ко пор­тов, которые прос­лушива­ются толь­ко для localhost.

Активные порты
Ак­тивные пор­ты

В катало­ге /opt есть две инте­рес­ные дирек­тории: containerd и portainer.

Содержимое каталога /opt
Со­дер­жимое катало­га /opt

Portainer — это плат­форма для управле­ния дос­тавкой кон­тей­нер­ных при­ложе­ний, которая может исполь­зовать­ся в сочета­нии со сре­дами вро­де Docker и Kubernetes.

Содержимое каталога /opt/portainer
Со­дер­жимое катало­га /opt/portainer

Эта плат­форма дос­тупна как раз на пор­тах 9000 и 9443, которые прос­лушива­ются на локаль­ном хос­те. Что­бы получить дос­туп к Portainer, нам нуж­но будет про­кинуть порт 9000 на свой хост с помощью SSH.

ssh -i id_rsa john@runner.htb -L 9000:127.0.0.1:9080 -N

Те­перь весь тра­фик, который мы пош­лем на локаль­ный порт 9000, будет тун­нелиро­ван на порт 9080 ука­зан­ного хос­та (в дан­ном слу­чае 127.0.0.1) через хост SSH.

Форма авторизации Portainer
Фор­ма авто­риза­ции Portainer

У нас нет никаких учет­ных дан­ных для вхо­да, поэто­му я решил вер­нуть­ся к най­ден­ной в бэкапах базе и переб­рать сох­ранен­ные в ней хеши. Прос­то запуск hashcat при­ведет к тому, что ути­лита не смо­жет самос­тоятель­но опре­делить алго­ритм хеширо­вания и пред­ложит нес­коль­ко вари­антов.

hashcat hashes.txt rockyou.txt
Справка hashcat
Справ­ка hashcat

Вы­бира­ем самый популяр­ный — режим 3200 — и пов­торя­ем брут.

hashcat -m 3200 hashes.txt rockyou.txt
Результат работы hashcat
Ре­зуль­тат работы hashcat

Спус­тя минуту hashcat находит пароль поль­зовате­ля matthew, от име­ни которо­го получа­ется авто­ризо­вать­ся в Portainer.

Главная страница Portainer
Глав­ная стра­ница Portainer

Локальное повышение привилегий

Пе­рехо­дим в окру­жение Primary и на стра­нице Dashboard смот­рим, что нам дос­тупно.

Содержимое страницы Dashboard
Со­дер­жимое стра­ницы Dashboard

Пер­вая идея, которая меня посети­ла, — про­верить, нет ли уяз­вимос­ти CVE-2024-21626 в runС млад­ше вер­сии 1.1.11. Этот баг поз­воля­ет вый­ти из кон­тей­нера.

RunC — это сре­да выпол­нения, которая при­меня­ется для соз­дания и запус­ка кон­тей­неров с раз­ными парамет­рами изо­ляции, такими как прос­транс­тва имен, кон­троль­ные груп­пы, Linux Capabilities и так далее. Один из этих методов — исполь­зование отдель­ной фай­ловой сис­темы в качес­тве кор­невой ФС кон­тей­нера (это дос­тига­ется через chroot).

Рас­смат­рива­емая уяз­вимость зак­люча­ется в утеч­ке фай­лового дес­крип­тора, который может быть исполь­зован новым кон­тей­нером, что­бы соз­дать рабочий каталог в прос­транс­тве имен хос­товой фай­ловой сис­темы и тем самым обой­ти chroot. В дан­ном слу­чае утеч­ка дес­крип­тора про­исхо­дит через /proc/self/fd/, который содер­жит фай­ловые дес­крип­торы текуще­го про­цес­са, а runC, в свою оче­редь, соз­дает дес­крип­тор /sys/fs/cgroup, дос­тупный через /proc/self/fd/ по номерам 7, 8 или 9.

Та­ким обра­зом, если при соз­дании кон­тей­нера в качес­тве рабоче­го катало­га ука­зать дес­крип­тор /proc/self/fd/8, то реаль­ным рабочим катало­гом кон­тей­нера ста­нет хос­товый путь /sys/fs/cgroup. А это поможет дотянуть­ся до любого фай­ла хос­товой фай­ловой сис­темы через вот такой обход путей:

../../../../

В Portainer уже есть два готовых обра­за, будем исполь­зовать один из них. На стра­нице Images выбира­ем образ и на стра­нице Image details копиру­ем ID обра­за.

Страница Images
Стра­ница Images
Страница Image details
Стра­ница Image details

За­тем перехо­дим на стра­ницу Containers и соз­даем кон­тей­нер. В поле Image ука­зыва­ем ID обра­за, а в рас­ширен­ных нас­трой­ках кон­тей­нера — рабочий каталог /proc/self/fd/8.

Настройки контейнера
Нас­трой­ки кон­тей­нера
Расширенные настройки контейнера
Рас­ширен­ные нас­трой­ки кон­тей­нера

Пос­ле стар­та кон­тей­нера под­клю­чаем­ся к нему и про­буем читать файл /etc/hostname на хос­товой сис­теме.

Список контейнеров
Спи­сок кон­тей­неров
Консоль контейнера
Кон­соль кон­тей­нера

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

Флаг рута
Флаг рута

И машина зах­вачена!