I recently updated the last installment in my AD series – Active Directory Certificate Services (ADCS) Misconfiguration Exploits – with a few new tricks I discovered recently on an engagement. I mentioned that I have seen web enrollment where it does not listen on port 80 (HTTP), which is the default for certipy. I ran into some weird issues with certipy when testing on port 443, and I found that NTLMRelayx.py worked better in that case. As promised, here is a short blog explaining what I did.
This is basically the same thing as using certipy – just a different set of commands. So here we will go through an example and see how it works.
The first part of the command points to the target. Make sure to include the endpoint (/certsrv/certfnsh.asp) as NTLMRelay won’t know that on its own. Also make sure to tell NTLMRelay if the host is HTTP or HTTPS.
The adcs flag tells NTLMRelay that we are attacking ADCS, and the template flag is used to specify the template. This is needed if you are relaying a domain controller or want to target a specific template. However, if you are planning on just relaying machines or users, you can actually leave this part out.
As connections come in, NTLMRelay will figure out on its own whether it’s a user or machine account and request the proper certificate. It does this based on whether the incoming username ends in a dollar sign. If it ends in a dollar sign NTLMRelay requests a machine certificate, if not it requests a user certificate.
Once NTLMRelay gets a successful relay, it will return a large Base64 blob of data. This is a Base64 encoded certificate.
You can take this Base64 blob and save it to a file. Then just decode the Base64 and save that as a PFX certificate file. After that the attack is the same as the certipy attack in my previous blog. Just use the certificate to login.
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.
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}
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.
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:
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
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 PetitPotam.py -u {Username} -p {Password} {Listener IP Address} {Target IP Address}
After Certipy receives the connection it will relay the connection and get a certificate for the domain controller machine account.
We can then use Certipy to authenticate with the certificate, which gives access to the domain controller’s machine account 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.
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.
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.
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}
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}
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}
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}
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.
Now we use Certipy to show the vulnerable templates using the same command as we used in the prior exploits.
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}
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}
Before we get too far, it’s a good idea to restore the certificate 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}
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}
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}'
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}