Се­год­ня мы раз­берем «безум­ную» по слож­ности машину с Hack The Box. Она называ­ется Pivotapi и пос­вящена пен­тесту Active Directory. Нам пред­сто­ит занять­ся OSINT, про­вес­ти ата­ку AS-Rep Roasting, деком­пилиро­вать при­ложе­ние на .NET, получить точ­ку опо­ры через эксфиль­тра­цию дан­ных из Microsoft SQL, взло­мать базу KeePass, про­экс­плу­ати­ровать LAPS для повыше­ния при­виле­гий и поюзать BloodHound. Прог­рамма очень плот­ная, начина­ем немед­ля!

warning

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

 

Разведка. Сканирование портов

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

10.10.10.240 pivotapi.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).

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

Мы наш­ли мно­го откры­тых пор­тов, давай прой­дем­ся по поряд­ку:

  • 21 — служ­ба FTP (дос­тупен ано­ним­ный вход);
  • 22 — служ­ба SSH;
  • 53 — служ­ба DNS;
  • 88 — служ­ба авто­риза­ции Kerberos;
  • 135 — служ­ба уда­лен­ного вызова про­цедур (Microsoft RPC);
  • 139 — служ­ба имен NetBIOS;
  • 389, 636, 3268, 3269 — служ­ба LDAP;
  • 445 — служ­ба SMB;
  • 464 — служ­ба сме­ны пароля Kerberos;
  • 593 — служ­ба уда­лен­ного вызова про­цедур (Microsoft RPC над HTTPS);
  • 1433 — Microsoft SQL Server 2019;
  • 9383 — служ­ба шлю­зов управле­ния Active Directory.

В ито­ге мы получа­ем очень важ­ную информа­цию. Во‑пер­вых, мы можем работать со служ­бой FTP без авто­риза­ции, а во‑вто­рых, SQL Server дал нам име­на домена (LICORDEBELLOTA) и текущей машины (PIVOTAPI).

Да­вай ска­чаем все фай­лы с FTP-сер­вера для даль­нейше­го ана­лиза. Сде­лаем это с помощью wget:

wget ftp://pivotapi.htb/*

В докумен­тах ничего важ­ного для прод­вижения не наш­лось, но тема инте­рес­ная — они опи­сыва­ют спо­собы экс­плу­ата­ции раз­личных уяз­вимос­тей. Но, как отме­чает­ся в любом кур­се OSINT (раз­ведка на осно­ве откры­тых источни­ков), если мы смог­ли получить какие‑либо докумен­ты, нас могут заин­тересо­вать метадан­ные, а имен­но атри­буты «соз­датель» и «вла­делец». Из них иног­да мож­но узнать име­на, под­ходящие в качес­тве логинов. Смот­реть эти дан­ные мож­но раз­ными метода­ми, я вос­поль­зуюсь exiftool (уста­нав­лива­ется коман­дой sudo apt install exiftool).

Свойства документа notes1.pdf
Свой­ства докумен­та notes1.pdf

Соз­дав прос­той кон­вей­ер на Bash, получим из всех докумен­тов поля Creator и Author.

exiftool * | grep "Creator\|Author" | awk '{print $3}'
Владельцы и создатели файлов
Вла­дель­цы и соз­датели фай­лов

От­кинув сом­нитель­ные записи, мы можем сос­тавить спи­сок из пяти воз­можных имен поль­зовате­лей: saif, byron, cairo, Kaorz, alex.

 

Точка входа. AS-Rep Roasting

Так как на хос­те работа­ет Kerberos, мы можем про­верить, сущес­тву­ет ли какая‑то учет­ная запись. В этом нам поможет ата­ка AS-Rep Roasting. Смысл ее в том, что мы посыла­ем на сер­вер аутен­тифика­ции ано­ним­ный зап­рос для пре­дос­тавле­ния опре­делен­ному поль­зовате­лю дос­тупа к какой‑либо услу­ге. Сер­вер в ответ:

  • пре­дос­тавля­ет хеш;
  • от­веча­ет, что у дан­ного поль­зовате­ля не выс­тавлен флаг UAF Don't Require PreAuth;
  • го­ворит, что такого поль­зовате­ля нет в базе Kerberos.

Вы­пол­нить ата­ку мы можем с помощью скрип­та GetNPUsers, вхо­дяще­го в сос­тав пакета скрип­тов impacket. Зада­ем скрип­ту сле­дующие парамет­ры: кон­трол­лер домена (-dc-ip), спо­соб аутен­тифика­ции Kerberos (-k), опция «без пароля» (-no-pass), спи­сок поль­зовате­лей (-usersfile) и целевой хост в фор­мате домен/хост.

GetNPUsers.py -dc-ip 10.10.10.240 -no-pass -k -usersfile users.txt LICORDEBELLOTA/pivotapi.htb
Результат работы скрипта
Ре­зуль­тат работы скрип­та

Нам говорят, что, кро­ме поль­зовате­ля Kaorz, в базе Kerberos боль­ше никого нет, при­чем для учет­ной записи Kaorz сер­вер аутен­тифика­ции вер­нул нам хеш! Давай раз­берем­ся, что это за хеши и почему их раз­дают кому попало.

Де­ло в том, что, ког­да кли­ент посыла­ет сооб­щение c иден­тифика­тором поль­зовате­ля на сер­вер аутен­тифика­ции и зап­рашива­ет дос­туп к услу­ге для какого‑то поль­зовате­ля, сер­вер аутен­тифика­ции смот­рит, есть ли поль­зователь в базе Kerberos, пос­ле чего про­веря­ет его учет­ные дан­ные. Если учет­ные дан­ные невер­ны, сер­вер отве­чает сооб­щени­ем UAF Don’t Require PreAuth.

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

Бру­тить хеш будем по сло­варю прог­раммой hashcat. При запус­ке нам нуж­но передать номер типа хеша (параметр -m), поэто­му сна­чала узна­ем его, зап­росив справ­ку и отфиль­тро­вав толь­ко нуж­ный нам тип.

hashcat --example | grep krb5asrep -A2 -B2
Получение номера типа хеша
По­луче­ние номера типа хеша

Ис­комый номер — 18200. Теперь запус­каем перебор, при этом в парамет­рах ука­зыва­ем перебор по сло­варю (-a 0), тип хеша krb5asrep (-m 18200), файл с хешем и сло­варь.

hashcat -a 0 -m 18200 hash.krb5asrep ~/wordlists/rockyou.txt
Результат перебора хеша
Ре­зуль­тат перебо­ра хеша

Очень быс­тро находим иско­мый пароль учет­ной записи Kaorz. Так как у нас появи­лись учет­ные дан­ные, нуж­но поп­робовать с ними под­клю­чить­ся ко всем дос­тупным ресур­сам. FTP учет­ных дан­ных не тре­бует, поэто­му про­верим SMB. Для это­го я обыч­но исполь­зую ути­литу smbmap.

smbmap -u Kaorz -p Roper4155 -H 10.10.10.240
Доступные ресурсы SMB
Дос­тупные ресур­сы SMB

В выводе получим спи­сок дос­тупных ресур­сов SMB и раз­решения для каж­дого. Что­бы дол­го не ходить по дирек­тори­ям и не искать инте­рес­ные фай­лы, есть удоб­ная воз­можность вывес­ти все содер­жимое ресур­сов рекур­сивно. Для это­го в smbmap нуж­но ука­зать опцию -R. Про­лис­тав спи­сок, обра­щаем вни­мание на каталог HelpDesk, который содер­жит исполня­емый файл и два фай­ла msg, то есть какие‑то сооб­щения.

smbmap -u Kaorz -p Roper4155 -H 10.10.10.240 -R
Содержимое каталога HelpDesk
Со­дер­жимое катало­га HelpDesk

Что­бы заполу­чить фай­лы, можем запус­тить любой кли­ент SMB. Я буду исполь­зовать smbclient, пос­коль­ку он тоже вхо­дит в набор impacket.

smbclient.py LicorDeBellota/Kaorz:Roper4155@10.10.10.240
use NETLOGON
cd HelpDesk
get Restart-OracleService.exe
get Server MSSQL.msg
get WinRM Service.msg
exit
Загрузка файлов с SMB
Заг­рузка фай­лов с SMB
 

Точка опоры

 

Конвертация MSG

Файл .msg содер­жит элек­трон­ное пись­мо в фор­мате Microsoft Outlook и вклю­чает дан­ные отпра­вите­ля и получа­теля, тему и текст пись­ма. Так­же в виде фай­ла .msg может быть сох­ранена информа­ция о встре­че или ином событии из кален­даря Outlook, дан­ные кон­такта из адресной кни­ги, све­дения о задаче. Его мож­но кон­верти­ровать в обыч­ный тек­сто­вый фор­мат с помощью ути­литы msgconvert. Но сна­чала ее сле­дует уста­новить.

sudo apt install libemail-outlook-message-perl libemail-sender-perl
msgconvert Server\ MSSQL.msg
msgconvert WinRM\ Service.msg
Содержимое сообщения Server MSSQL
Со­дер­жимое сооб­щения Server MSSQL
Содержимое сообщения WinRM Service
Со­дер­жимое сооб­щения WinRM Service

В пер­вом сооб­щении говорит­ся, что в 2010-е годы была уста­нов­лена база Oracle, но в 2020 году решили перей­ти на MS SQL. При этом най­ден­ное при­ложе­ние Reset-Service.exe было соз­дано для рес­тарта служ­бы Oracle. Что здесь очень важ­но — это фун­кция логина, то есть при­ложе­ние работа­ет с учет­ными дан­ными.

Во вто­ром сооб­щении упо­мина­ется бло­киров­ка служ­бы WinRM и исхо­дяще­го тра­фика по про­токо­лам TCP, UDP и ICMP.

 

Анализ приложения, использующего вызов CMD

Пе­рей­дем к ана­лизу треть­его фай­ла — исполня­емо­го. Откро­ем его в любом дизас­сем­бле­ре (я исполь­зую IDA Pro) и пер­вым делом гля­нем спи­сок импорти­руемых фун­кций. Это поз­волит нам сос­тавить пер­вое мне­ние об этой прог­рамме и при­мер­но понять, для чего она нуж­на.

Список импортируемых функций
Спи­сок импорти­руемых фун­кций

Об­ратим вни­мание на фун­кцию ShellExecuteEx, которая дол­жна выпол­нять коман­ды в коман­дной стро­ке. Еще здесь мно­го фун­кций для работы с фай­лами (DeleteFile, CreateFile, GetTempPathW и про­чие). Что­бы наг­лядно отсле­дить работу с фай­лами и запуск команд, акти­виру­ем Process Monitor. Пос­ле запус­ка соз­дадим филь­тр, который будет отсле­живать толь­ко наш целевой про­цесс.

Фильтр Process Monitor
Филь­тр Process Monitor

Ког­да все будет готово, запус­тим исполня­емый файл и прос­мотрим вывод Process Monitor.

События в Process Monitor
Со­бытия в Process Monitor

В событи­ях мы видим соз­дание фай­лов .tmp и запись (ско­рее все­го, копиро­вание) скрип­та .bat. Далее соз­дает­ся про­цесс коман­дно­го интер­пре­тато­ра cmd.exe. А раз он запус­кает­ся, то мы можем вос­поль­зовать­ся CMDWatcher. Эта ути­лита будет при­оста­нав­ливать про­цесс и показы­вать аргу­мен­ты при запус­ке CMD в любых про­цес­сах. Запус­тим CMDWatcher, а потом ана­лизи­руемое при­ложе­ние. Мы уви­дим, как запус­кает­ся при­ложе­ние, а затем — как акти­виру­ется сце­нарий bat.

Событие запуска приложения Restart-OracleService.exe
Со­бытие запус­ка при­ложе­ния Restart-OracleService.exe
Событие запуска файла bat
Со­бытие запус­ка фай­ла bat

Прой­дем в дирек­торию с запус­каемым скрип­том и уви­дим в ней сам скрипт и файл с рас­ширени­ем tmp.

Содержимое каталога /AppData/Local/Temp/
Со­дер­жимое катало­га /AppData/Local/Temp/

Заг­лянем в скрипт. В начале видим про­вер­ку на запуск от име­ни опре­делен­ного поль­зовате­ля. Сра­зу сох­раня­ем себе его имя — при­годит­ся! Затем дан­ные записы­вают­ся в файл C:\programdata\oracle.txt. Кодиров­ка напоми­нает Base64.

Содержимое скрипта
Со­дер­жимое скрип­та

Пос­ле записи соз­дает­ся еще один файл — C:\programdata\monta.ps1, он содер­жит код на PowerShell. Этот код счи­тыва­ет дан­ные из фай­ла C:\programdata\oracle.txt, декоди­рует их из Base64 и записы­вает в C:\programdata\restart-service.exe. Затем уда­ляют­ся и файл с дан­ными Base64, и скрипт на PowerShell и запус­кает­ся новосоз­данный исполня­емый файл restart-service.exe. Пос­ле выпол­нения он уда­ляет­ся.

Содержимое скрипта
Со­дер­жимое скрип­та

Да­вай получим этот исполня­емый файл для даль­нейше­го ана­лиза. Для это­го нем­ного модер­низиру­ем наш бат­ник: в начале скрип­та убе­рем про­вер­ку поль­зовате­лей, а в кон­це — любые уда­ления фай­лов (коман­да del), убе­рем так­же запуск соз­дающе­гося исполня­емо­го фай­ла.

Модернизированный bat-скрипт (начало)
Мо­дер­низиро­ван­ный bat-скрипт (начало)
Модернизированный bat-скрипт (конец)
Мо­дер­низиро­ван­ный bat-скрипт (конец)

За­пус­тим изме­нен­ный скрипт, пос­ле чего про­верим каталог C:\programdata, там нас будет ждать файл с дан­ными, скрипт на PowerShell и целевая прог­рамма.

Содержимое каталога C:\programdata
Со­дер­жимое катало­га C:\programdata
 

Анализ приложения со скрытыми функциями

Ис­полня­емый файл откры­ваем в IDA Pro, что­бы пос­мотреть импорти­руемые фун­кции. Но там не было ничего инте­рес­ного, а для ста­тичес­кого ана­лиза файл велико­ват. Имен­но по этой при­чине я решил исполь­зовать при­ложе­ние API Monitor. Оно может отоб­ражать все вызовы API-фун­кций вмес­те с переда­ваемы­ми в них аргу­мен­тами.

Пос­ле запус­ка API Monitor нуж­но ука­зать целевой исполня­емый файл, для чего выбира­ем Monitor New Process. В раз­деле спра­ва уви­дим все выз­ванные при­ложе­нием фун­кции.

Стартовое окно приложения API Monitor
Стар­товое окно при­ложе­ния API Monitor
Выбор исполняемого файла
Вы­бор исполня­емо­го фай­ла
Результат анализа файла
Ре­зуль­тат ана­лиза фай­ла

Час­то вызыва­ется GetProcAddress. Дело в том, что DLL может заг­ружать­ся при­ложе­нием не толь­ко ста­тичес­ки (при запус­ке), но и динами­чес­ки (во вре­мя выпол­нения) с помощью фун­кции LoadLibrary. А для получе­ния адре­са фун­кции в заг­ружен­ной DLL как раз исполь­зует­ся фун­кция GetProcAddress, которая в качес­тве парамет­ра получа­ет имя импорти­руемой фун­кции. Эта тех­ника усложня­ет ста­тичес­кий ана­лиз, а имен­но скры­вает важ­ные фун­кции из таб­лицы импорта.

Да­вай узна­ем, какие фун­кции хотел спря­тать раз­работ­чик. Для это­го необ­ходимо уста­новить филь­тр, что­бы в выводе при­сутс­тво­вали толь­ко фун­кции GetProcAddress. В кон­текс­тном меню выбира­ем Include → API Name.

Установка фильтра
Ус­танов­ка филь­тра
Отфильтрованный список функций API
От­филь­тро­ван­ный спи­сок фун­кций API

Сра­зу видим мно­жес­тво фун­кций для работы с реес­тром, но это пока ничего не говорит. Что­бы сло­жить целос­тную кар­тину, прос­мотрим абсо­лют­но все заг­ружа­емые фун­кции (это зай­мет 5–10 минут). Во вре­мя ана­лиза оста­нав­лива­емся на CreateProcessWithLogonW. Это важ­ная фун­кция!

Отфильтрованный список API-функций
От­филь­тро­ван­ный спи­сок API-фун­кций

Она соз­дает новый про­цесс и его пер­вичный глав­ный поток. Новый про­цесс затем запус­кает задан­ный исполня­емый файл в кон­тек­сте сис­темы безопас­ности опре­делен­ного поль­зовате­ля. Дело в том, что эта фун­кция при­нима­ет учет­ные дан­ные поль­зовате­ля в качес­тве аргу­мен­тов. Давай най­дем ее вызов, что­бы получить эти парамет­ры. Для это­го выбира­ем в окне Display пункт Add Filter, а затем ука­зыва­ем усло­вие API Name is CreateProcessWithLogonW.

Создание фильтра
Соз­дание филь­тра
Событие вызова функции CreateProcessWithLogonW
Со­бытие вызова фун­кции CreateProcessWithLogonW

Об­рати вни­мание на парамет­ры lpUsername и lpPassword, где содер­жатся имя поль­зовате­ля и его пароль. Так как это учет­ные дан­ные для сер­вера базы дан­ных, поп­робу­ем на нем и авто­ризо­вать­ся. Увы, моя пер­вая попыт­ка зай­ти как svc_oracle:#oracle_s3rV1c3!2010 про­вали­лась — сер­вер отве­тил, что имя поль­зовате­ля или пароль невер­ные.

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    1 Комментарий
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии